PostgreSQL объединение количества, количества последних 7 дней и последних 30 дней Сгруппировано по дням - PullRequest
1 голос
/ 04 мая 2020

У меня есть небольшая таблица (TABLEA) с двумя столбцами IDA и DATETIMEA.

TABLEA

IDA  DATETIMEA
1    2020-03-16 13:15:00
2    2020-03-17 15:25:00
3    2020-03-18 17:10:00
5    2020-03-19 11:44:00
5    2020-03-20 12:55:00
5    2020-03-21 19:35:00
7    2020-03-22 10:13:00
8    2020-03-22 15:25:00
8    2020-03-28 12:12:00
9    2020-03-29 17:55:00
10   2020-03-30 11:54:00
12   2020-03-30 15:35:00
12   2020-03-31 13:19:00

Я пытаюсь чтобы получить общее количество IDA в день, всего за последние 7 дней и всего за последние 30 дней.

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

DATE       DAY L7 L30
2020-03-16 1   1  1
2020-03-17 1   2  2
2020-03-18 1   3  3
2020-03-19 1   4  4
2020-03-20 1   5  5
2020-03-21 1   6  6
2020-03-22 2   8  8  
2020-03-28 1   3  9
2020-03-29 1   4  10
2020-03-30 2   6  12
2020-03-31 1   7  13

Я пробовал помещая связанные с датой выходные данные в подзапросы, но они возвращают 0.

SELECT t.DATETIMEA::date date,
COUNT(t.*) "day",
(SELECT COUNT(w.*) FROM TABLEA w WHERE w.DATETIMEA::date BETWEEN w.DATETIMEA::date AND w.DATETIMEA::date - 7) week,
(SELECT COUNT(m.*) FROM TABLEA m WHERE m.DATETIMEA::date BETWEEN m.DATETIMEA::date AND m.DATETIMEA::date - 30) "month"
FROM TABLEA t
GROUP BY t.DATETIMEA::date
ORDER BY t.DATETIMEA::date

Ответы [ 2 ]

2 голосов
/ 04 мая 2020

Если в ваших данных могут быть пропуски в днях, вам понадобится спецификация кадра range, а не кадр rows. К счастью, Postgres поддерживает эту спецификацию, поэтому вы можете:

select
    datetimea::date date,
    count(*) "day",
    sum(count(*)) over(
        order by datetimea::date
        range between '7 day' preceding and current row
    ) l7,
        sum(count(*)) over(
        order by datetimea::date
        range between '30 day' preceding and current row
    ) l30
from mytable
group by datetimea::date
order by datetimea::date 

Демо на DB Fiddle :

date       | day | l7 | l30
:--------- | --: | -: | --:
2020-03-16 |   1 |  1 |   1
2020-03-17 |   1 |  2 |   2
2020-03-18 |   1 |  3 |   3
2020-03-19 |   1 |  4 |   4
2020-03-20 |   1 |  5 |   5
2020-03-21 |   1 |  6 |   6
2020-03-22 |   2 |  8 |   8
2020-03-28 |   1 |  4 |   9
2020-03-29 |   1 |  4 |  10
2020-03-30 |   2 |  4 |  12
2020-03-31 |   1 |  5 |  13
2 голосов
/ 04 мая 2020

Я думаю, что оконные функции делают то, что вы хотите:

select t.datetimea::date, count(*) as on_day,
       sum(count(*)) over (order by t.datetimea::date rows between 6 preceding and current row) as sum_7,
       sum(count(*)) over (order by t.datetimea::date rows between 29 preceding and current row) as sum_30
from tablea t
group by t.datetimea::date;

Под «последними 7 днями», я полагаю, вы имеете в виду сегодняшний и предыдущие 6 дней. Если вы имеете в виду за 7 дней до сегодняшнего дня, оконную раму можно легко отрегулировать.

...