PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

usando alias coalesce in una condizione:coalesce (max(case when value then value ) as alias

Per discussione nei commenti, perché ti aspetti ogni ad_id in ad_params avere un unico value per name , possiamo riscrivere il tuo codice come di seguito e aggiungere facilmente il filtro richiesto:

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;
*/

Se vuoi qualcosa di più in linea con il tuo SQL originale, funzionerebbe anche quanto segue:

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;

Possiamo riscriverlo anche in molti altri modi; ma per scegliere il bset avremmo bisogno di saperne di più sul tuo schema e sui tuoi dati. Questo post fornisce alcune informazioni utili correlate:https://stackoverflow.com/a/7449213/361842 (sebbene si concentri su MSSQL piuttosto che su Postgres; ma si applicano idee simili).