PostgreSQL:使用Generate_Series()计数0

PostgreSQL:使用Generate_Series()计数0,sql,postgresql,group-by,count,generate-series,Sql,Postgresql,Group By,Count,Generate Series,我试图统计过去7天的记录,包括那些没有任何记录或0的记录。这是我目前的问题 WITH calendar as ( SELECT d FROM generate_series(date_trunc('day',CURRENT_DATE - '7 day'::interval - '7 hour'::interval),date_trunc('day', CURRENT_DATE - INTERVAL '7 hour'), '1 day'::interval) d ) SELECT

我试图统计过去7天的记录,包括那些没有任何记录或0的记录。这是我目前的问题

WITH calendar as (
SELECT  d
FROM generate_series(date_trunc('day',CURRENT_DATE - '7 day'::interval - '7 hour'::interval),date_trunc('day', CURRENT_DATE - INTERVAL '7 hour'), '1 day'::interval) d 
)

SELECT 
        COUNT(mc.id), 
        mc.name AS ord_name, 
        c.d::date AS ord_date
    FROM test_table mc
    LEFT JOIN calendar c
    ON c.d = mc.occured_at::date
    WHERE date_trunc('day', occured_at - interval '7 hour') > 
    (CURRENT_DATE + INTERVAL '7 hour') - INTERVAL '7 days'
    GROUP BY 
        name, 
        c.d
    ORDER BY 
        c.d;
我的查询结果与

所以我使用generate_系列来获取我想要的日期。我减去7小时,因为从技术上讲,一天从早上7点开始,到第二天早上6点59分结束。我使用LEFT JOIN来比较我从日历中获得的日期和我的表的日期

样本数据:测试表

预期结果:


顺便说一句,use calendar table in left btw order是关键字,所以最好不要使用任何关键字作为表名,因为您已经使用过了,所以请使用双引号

WITH calendar as (
SELECT  d
FROM generate_series(date_trunc('day',CURRENT_DATE - '7 day'::interval - '7 hour'::interval),date_trunc('day', CURRENT_DATE - INTERVAL '7 hour'), '1 day'::interval) d 
)

SELECT 
        COUNT(mc.id), 
        mc.name AS ord_name, 
        c.d::date AS ord_date
    FROM 
      calendar c LEFT JOIN 
      "order" mc  
    ON c.d = mc.occured_at::date
    WHERE date_trunc('day', occured_at - interval '7 hour') > 
    (CURRENT_DATE + INTERVAL '7 hour') - INTERVAL '7 days'
    GROUP BY 
        name, 
        c.d
    ORDER BY 
        c.d;
使用交叉联接生成所有行,然后使用左联接引入具有匹配值的行:

WITH calendar as (
      SELECT d
      FROM generate_series(date_trunc('day', CURRENT_DATE - '7 day'::interval - '7 hour'::interval),
                           date_trunc('day', CURRENT_DATE - INTERVAL '7 hour'),
                          '1 day'::interval
                          ) d 
     )

SELECT n.name AS ord_name, 
       c.d::date AS ord_date
       COUNT(mc.id), 
FROM (SELECT DISTINCT mc.name test_table mc) n CROSS JOIN
     calendar c LEFT JOIN
     test_table mc
     ON mc.occured_at >= c.d - interval '7 hour' and
        mc.occured_at < c.d + interval '1 day' - interval '7 hour'
GROUP BY n.name, c.d
ORDER BY c.d, n.name;

谢谢你的回答Zaynul,显然我已经试过了,但我仍然错过了一些日期。@Paolo你丢失的日期数据我编辑了我的问题,并添加了一个DB FIDLE链接,其中包含示例数据。嘿,戈登,谢谢你的回答。现在所有的日期都显示出来了,我唯一担心的是查询会统计当天上午12点到晚上11点59分的记录。有没有可能把这段时间调整到第二天早上7点到6点59分。您可以通过比较中的日期算术来解决这个问题。
WITH calendar as (
SELECT  d
FROM generate_series(date_trunc('day',CURRENT_DATE - '7 day'::interval - '7 hour'::interval),date_trunc('day', CURRENT_DATE - INTERVAL '7 hour'), '1 day'::interval) d 
)

SELECT 
        COUNT(mc.id), 
        mc.name AS ord_name, 
        c.d::date AS ord_date
    FROM 
      calendar c LEFT JOIN 
      "order" mc  
    ON c.d = mc.occured_at::date
    WHERE date_trunc('day', occured_at - interval '7 hour') > 
    (CURRENT_DATE + INTERVAL '7 hour') - INTERVAL '7 days'
    GROUP BY 
        name, 
        c.d
    ORDER BY 
        c.d;
WITH calendar as (
      SELECT d
      FROM generate_series(date_trunc('day', CURRENT_DATE - '7 day'::interval - '7 hour'::interval),
                           date_trunc('day', CURRENT_DATE - INTERVAL '7 hour'),
                          '1 day'::interval
                          ) d 
     )

SELECT n.name AS ord_name, 
       c.d::date AS ord_date
       COUNT(mc.id), 
FROM (SELECT DISTINCT mc.name test_table mc) n CROSS JOIN
     calendar c LEFT JOIN
     test_table mc
     ON mc.occured_at >= c.d - interval '7 hour' and
        mc.occured_at < c.d + interval '1 day' - interval '7 hour'
GROUP BY n.name, c.d
ORDER BY c.d, n.name;