Postgresql
加入表並返回計數,即使它是 0
我有這個查詢:
select settings.customer_id, current::jsonb->'alarms' as alarms, from settings join (select customer_id, current::jsonb->'alarms' as alarms from settings) as res on res.customer_id=settings.customer_id where res.alarms is not null;
返回
+------------------+ |customer_id|alarms| |1 |{...} | |2 |{...} | |3 |{...} | +------------------+
然後我有另一個實體
registration
,其中欄位customer_id
和date
位置date
是類型date
,並且我以格式儲存值YYYY-MM-DD
。我想要實現的是加入
registration
實體customer_id
併計算registration
給定單個日期 fe 的記錄'2018-11-20'
。但是(這是吸引人的部分)我想以某種方式檢索它,因此如果該日期沒有註冊記錄,則返回 0,否則返回實際數字。使用到目前為止我嘗試過的解決方案,我只會得到具有
alarms
AND 註冊的記錄,就好像我有這個:select settings.customer_id, current::jsonb->'alarms' as alarms, coalesce(regs.count, 0) from settings join (select customer_id, current::jsonb->'alarms' as alarms from settings) as res on res.customer_id=settings.customer_id join (select customer_id, count(customer_id) from registration where date='2018-11-20' group by customer_id) as regs on settings.customer_id=reg.customer_id where res.alarms is not null;
或者
select settings.customer_id, current::jsonb->'alarms' as alarms, coalesce(count(regs.customer_id), 0) from settings join (select customer_id, current::jsonb->'alarms' as alarms from settings) as res on res.customer_id=settings.customer_id join registration as regs on settings.customer_id=regs.customer_id where res.alarms is not null and regs.date='2018-10-10' group by settings.customer_id, settings.current;
如果我換一種說法:獲取具有
alarms
對象的記錄,並獲取給定日期的註冊數量,無論它是 0 還是 > 0。
LEFT JOIN
是關鍵,就像 ypercube 評論的那樣。而且您可能不需要自加入 - 假設
settings.customer_id
是unique not null
.如果您的謂詞是選擇性的(多於幾行沒有警報),我建議計入
LATERAL
子查詢:SELECT s.customer_id, s.current::jsonb->'alarms' AS alarms , coalesce(r.reg_ct, 0) AS reg_ct FROM settings s LEFT JOIN LATERAL ( SELECT count(*) AS reg_ct FROM registration WHERE customer_id = s.customer_id AND date = '2018-10-10' ) r ON true WHERE s.current::jsonb->'alarms' IS NOT NULL;
否則,一個普通的子查詢應該更快:
SELECT s.customer_id, s.current::jsonb->'alarms' AS alarms , coalesce(r.reg_ct, 0) AS reg_ct FROM settings s LEFT JOIN ( SELECT customer_id, count(*) AS reg_ct FROM registration WHERE date = '2018-10-10' GROUP BY 1 ) r USING (customer_id) WHERE s.current::jsonb->'alarms' IS NOT NULL;
無論哪種方式,在加入之前聚合通常更快且更不容易出錯。
有關的: