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).