PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Verwendung von Alias ​​Coalesce in einer Bedingung:Coalesce (max(case when value then value ) als Alias

Per Diskussion in den Kommentaren, weil Sie jede ad_id erwarten in ad_params einen einzigen value haben pro name , können wir Ihren Code wie folgt umschreiben und den erforderlichen Filter ganz einfach hinzufügen:

select ad_media.ad_media_id
, ad_media.ad_id
, ads.name
, action_states.timestamp
, regdate.value AS regdate
, mileage.value AS mileage
, fuel.value AS fuel
, brand.value AS brand
, model.value AS model

from ad_media 
inner join action_states 
    on action_states.ad_id = ad_media.ad_id
inner join ads 
    on ads.ad_id = action_states.ad_id
left join ad_params as regdate --technically we could do an inner join here since we're using this in the WHERE clause now; but I'll leave as an outer join in case you need more advanced logic...
    on regdate.ad_id = ad_media.ad_id
    and regdate.name = 'regdate' 
left join ad_params as mileage
    on mileage.ad_id = ad_media.ad_id
    and mileage.name = 'mileage' 
left join ad_params as fuel
    on fuel.ad_id = ad_media.ad_id
    and fuel.name = 'fuel' 
left join ad_params as brand
    on brand.ad_id = ad_media.ad_id
    and brand.name = 'brand' 
left join ad_params as model
    on model.ad_id = ad_media.ad_id
    and model.name = 'model' 

where action_states.state = 'reg'   
and action_states.action_id = '1' 
and action_states.timestamp::DATE BETWEEN '2018-04-17' AND '2018-04-17'
and ads.category = '2010'   
and regdate.value = '2018' --your condition 

/* --this is probably no longer needed; if it is instead consider adding a `distinct`
group by ad_media.ad_media_id
, ad_media.ad_id
, ads.name
, action_states.timestamp 
order by ad_media.ad_id;
*/

Wenn Sie etwas mehr wünschen, das Ihrem ursprünglichen SQL entspricht, würde das Folgende auch funktionieren:

select ad_media.ad_media_id
, ad_media.ad_id
, ads.name
, action_states.timestamp
, max(CASE WHEN ad_params.name = 'regdate' THEN ad_params.value END) AS regdate
, max(CASE WHEN ad_params.name = 'mileage' THEN ad_params.value END) AS mileage
, max(CASE WHEN ad_params.name = 'fuel'    THEN ad_params.value END) AS fuel
, max(CASE WHEN ad_params.name = 'brand'   THEN ad_params.value END) AS brand
, max(CASE WHEN ad_params.name = 'model'   THEN ad_params.value END) AS model

from ad_media 
left join action_states 
    on action_states.ad_id = ad_media.ad_id
inner join ads 
    on ads.ad_id = action_states.ad_id
inner join ad_params --since we expect this filter to remove results, we now need it to be an inner join
    ad_params.ad_id = on ad_media.ad_id
    and 
    (
        ad_params.name != 'regdate' --\_i.e. if the value is regdate we want 2018; if it's not regdate we'll take any value
        or ad_params.value = '2018' --/
    )

where action_states.state = 'reg'   
and action_states.action_id = '1' 
and action_states.timestamp::DATE BETWEEN '2018-04-17' AND '2018-04-17'
and ads.category = '2010'   

group by ad_media.ad_media_id
, ad_media.ad_id
, ads.name
, action_states.timestamp 
order by ad_media.ad_id;

Wir können dies auch auf viele andere Arten umschreiben; aber um das bset auszuwählen, müssten wir mehr über Ihr Schema und Ihre Daten wissen. Dieser Beitrag enthält einige nützliche Informationen dazu:https://stackoverflow.com/a/7449213/361842 (konzentriert sich jedoch eher auf MSSQL als auf Postgres; aber ähnliche Ideen gelten).