我有以下查询:
SELECT created_at::DATE, count (*)
FROM messages
WHERE city = 'los angeles'
GROUP BY created_at::DATE
效果很好。挑战在于,如果给定日期没有消息,那么它不会返回该日期的记录。如果在给定日期和今天之间的所有日子里没有消息,您如何使上述查询返回日期和 0 ?
在 PostgreSQL 8.3 中工作。
谢谢!
我有以下查询:
SELECT created_at::DATE, count (*)
FROM messages
WHERE city = 'los angeles'
GROUP BY created_at::DATE
效果很好。挑战在于,如果给定日期没有消息,那么它不会返回该日期的记录。如果在给定日期和今天之间的所有日子里没有消息,您如何使上述查询返回日期和 0 ?
在 PostgreSQL 8.3 中工作。
谢谢!
典型的方法是有一个单独的日历表,其中包含所有日期,在日期列上左连接到您的表,然后使用某种 ifnull(x, 0) 语句[无论函数用于 PostgreSQL] 或 case 语句当日期的左连接返回 null 时返回 0 或不为 null 时返回 1。然后你可以做你的正常分组并使用 SUM(x) 而不是 count()。
听起来您需要一个包含您感兴趣的所有日期的表格,因为它可能包含不在您的消息表中的日期。如果您拥有或构建了此表,则与消息表保持连接,并依靠该表的列进行计数——它将返回 0,其中没有任何内容与连接匹配。
select d.created_at, count(m.messageId)
from possibleDates d
left join messages m
on d.created_at = m.created_at
group by d.created_at
很多时候,当您想为系列中的缺失条目填充零时,PostgreSQL 中的答案涉及该generate_series
函数。(在 Stackoverflow 上搜索很多类似的问题和答案。)在您的情况下,请使用以下内容:
SELECT ts::date AS date, coalesce(count, 0) AS count
FROM
(SELECT created_at::date, count(*)
FROM messages
WHERE city = 'los angeles'
GROUP BY created_at::date) AS m
RIGHT JOIN
(SELECT *
FROM generate_series(timestamp '2011-07-01',
timestamp 'today',
interval '1 day')) AS series(ts)
ON m.created_at = series.ts
ORDER BY 1;