PostgreSQL: COUNT 0 с Generate_Series () - PullRequest
       48

PostgreSQL: COUNT 0 с Generate_Series ()

0 голосов
/ 01 марта 2019

Я пытаюсь посчитать записи за последние 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;

Результат моего запроса с DB Fiddle Link

Result That I'm getting

Поэтому я использую generate_series (), чтобы получить нужные мне даты.Я вычитаю 7 часов, потому что технически день начнется в 7 утра и закончится в 6:59 утра следующего дня.Я использую LEFT JOIN для сравнения даты, полученной из календаря и даты в моей таблице.

Образцы данных: test_table


| id  |  name  |       occured_at     |
|-----|--------|----------------------|
| 1   |  ord1  |2019-02-23 07:00:00+00|
| 2   |  ord2  |2019-02-23 12:30:00+00|
| 3   |  ord1  |2019-02-24 06:58:00+00|
| 4   |  ord2  |2019-02-25 07:00:00+00|
| 5   |  ord2  |2019-02-25 07:01:00+00|
| 6   |  ord1  |2019-02-26 06:59:00+00|
| 7   |  ord1  |2019-02-26 07:00:00+00|
| 8   |  ord1  |2019-02-26 12:30:00+00|
| 9   |  ord2  |2019-02-27 06:58:00+00|
| 10  |  ord1  |2019-02-28 07:01:00+00|
| 11  |  ord1  |2019-02-28 07:00:00+00|
| 12  |  ord1  |2019-03-01 06:59:00+00|

Ожидаемый результат:

|count |ord_name |ord_date  |
|------|---------|----------|
| 1    |  ord1   |2019-02-23|
| 2    |  ord2   |2019-02-23|
| 0    |  ord1   |2019-02-24|
| 0    |  ord2   |2019-02-24|
| 1    |  ord1   |2019-02-25|
| 2    |  ord2   |2019-02-25|
| 2    |  ord1   |2019-02-26|
| 1    |  ord2   |2019-02-26|
| 0    |  ord1   |2019-02-27|
| 0    |  ord2   |2019-02-27|
| 3    |  ord1   |2019-02-28|
| 0    |  ord2   |2019-02-28|
| 0    |  ord1   |2019-03-01|
| 0    |  ord2   |2019-03-01|

Ответы [ 2 ]

0 голосов
/ 01 марта 2019

Используйте cross join для генерации всех строк и затем left join для ввода строк с совпадающими значениями:

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;
0 голосов
/ 01 марта 2019

использовать таблицу календаря в левом, кстати, порядке ключевого слова, поэтому лучше не использовать любое ключевое слово в качестве имени таблицы, как вы уже использовали, поэтому используйте двойную кавычку

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;
...