我在Postgres中有一个表employee
:
查询:
SELECT DISTINCT month_last_date,number_of_cases,reopens,csat
FROM employee
WHERE month_last_date >=(date('2017-01-31') - interval '6 month')
AND month_last_date <= date('2017-01-31')
AND agent_id='analyst'
AND name='SAM';
输出:
但如果其他月份的数据不在表中,我希望列值为 0
。
答案 0 :(得分:2)
生成您感兴趣的所有日期,LEFT JOIN
到表格,默认为0
COALESCE
:
SELECT DISTINCT -- see below
i.month_last_date
, COALESCE(number_of_cases, 0) AS number_of_cases -- see below
, COALESCE(reopens, 0) AS reopens
, COALESCE(csat, 0) AS csat
FROM (
SELECT date '2017-01-31' - i * interval '1 mon' AS month_last_date
FROM generate_series(0, 5) i -- see below
) i
LEFT JOIN employee e ON e.month_last_date = i.month_last_date
AND e.agent_id = 'analyst' -- see below
AND e.name = 'SAM';
如果您添加或减去1个月的interval
且目标月份中不存在同一天,则Postgres默认为该月的最新现有日期。所以这可以按照需要运行,你得到每个月的最后一天:
SELECT date '2017-12-31' - i * interval '1 mon' -- note 31
FROM generate_series(0,11) i;
但是 没有 ,你每个月都会获得第28名:
SELECT date '2017-02-28' - i * interval '1 mon' -- note 28
FROM generate_series(0,11) i;
安全的选择是从下个月的第一天减去1天,例如@Oto demonstrated。相关:
以下两种优化方法可以生成一个月的一系列最后几天 - 直到并包括某个月:
SELECT (timestamp '2017-01-01' - i * interval '1 month')::date - 1 AS month_last_date
FROM generate_series(-1, 10) i; -- generate 12 months, off-by-1
输入是 一月的第一天 - 或者使用date_trunc()
从给定的date
或timestamp
计算:
SELECT date_trunc('month', timestamp '2017-01-17')::date AS this_mon1
从interval
中减去date
会产生timestamp
。回到date
后,我们可以简单地减去integer
来减去天数。
SELECT m::date - 1 AS month_last_date
FROM generate_series(timestamp '2017-02-01' - interval '11 month' -- for 12 months
, timestamp '2017-02-01'
, interval '1 mon') m;
输入是 下个月的第一天 - 或者从任何给定的日期或时间戳计算它:
SELECT date_trunc('month', timestamp '2017-01-17' + interval '1 month')::date AS next_mon1
相关:
确定您确实需要 DISTINCT
。通常,(agent_id, month_last_date)
将被定义为唯一,然后移除DISTINCT
...
请务必正确使用 LEFT JOIN
。加入条件进入join子句, 不 WHERE
子句:
最后,0
默认为COALESCE
,NULL
填写LEFT JOIN
值。
注意 COALESCE
无法区分右表中的实际NULL
值和缺失行填充的NULL值。如果您的列未定义NOT NULL
,则可能存在歧义。
答案 1 :(得分:1)
如我所见,您需要在特定日期之前生成过去6个月的最后几天。 (在&#34; 2017-01-31&#34;在这种情况下)。
如果我正确理解,那么你可以使用这个生成所有这些日子的查询
SELECT (date_trunc('MONTH', mnth) + INTERVAL '1 MONTH - 1 day')::DATE
FROM
generate_series('2017-01-31'::date - interval '6 month', '2017-01-31'::date, '1 month') as mnth;
您只需要对现有查询进行LEFT JOIN
此查询,就可以得到理想的结果
请注意,这将返回7条记录(天),而不是6条。