Por discussão nos comentários, porque você espera cada
ad_id
em ad_params
ter um único value
por name
, podemos reescrever seu código conforme abaixo e adicionar facilmente o filtro necessário: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 você quiser algo mais de acordo com seu SQL original, o abaixo também funcionaria:
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;
Podemos reescrever isso de muitas outras maneiras também; mas para escolher o bset precisamos saber mais sobre seu esquema e dados. Esta postagem fornece algumas informações úteis relacionadas:https://stackoverflow.com/a/7449213/361842 (embora se concentre no MSSQL em vez do Postgres; mas ideias semelhantes se aplicam).