Mỗi cuộc thảo luận trong nhận xét, bởi vì bạn đang mong đợi mỗi ad_id
trong ad_params
để có một giá trị value
duy nhất per name
, chúng tôi có thể viết lại mã của bạn như bên dưới và dễ dàng thêm bộ lọc được yêu cầu:
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;
*/
Nếu bạn muốn thứ gì đó phù hợp hơn với SQL ban đầu của mình, thì cách bên dưới cũng sẽ hoạt động:
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;
Chúng ta cũng có thể viết lại điều này theo nhiều cách khác; nhưng để chọn bset, chúng tôi cần biết thêm về lược đồ và dữ liệu của bạn. Bài đăng này cung cấp một chút thông tin hữu ích có liên quan: https://stackoverflow.com/a/7449213/361842 (mặc dù tập trung vào MSSQL hơn là Postgres; nhưng các ý tưởng tương tự cũng được áp dụng).