SQL Агрегация окон для двух последовательных дат - PullRequest
5 голосов
/ 28 мая 2020

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

+---------+--------+--------+-------------+
| user_id | amount |  date  | sum_per_day |
+---------+--------+--------+-------------+
| user8   |   300  | 7/2/20 |     300     |
| user8   |   150  | 6/2/20 |     400     |
| user8   |   250  | 6/2/20 |     400     |
| user8   |   25   | 5/2/20 |     100     |
| user8   |   25   | 5/2/20 |     100     |
| user8   |   25   | 5/2/20 |     100     |
| user8   |   25   | 5/2/20 |     100     |
| user8   |   50   | 2/2/20 |     50      |
+---------+--------+--------+-------------+

Как вы видите, они сгруппированы по user_id. Теперь мне нравится добавлять столбец с именем sum_over_two_day, который удовлетворяет следующим условиям:

  1. Сгруппировано по user_id
  2. Для каждого пользователя он сгруппирован по date
  3. Затем сумма рассчитывается для двух последовательных календарных дней для amount (сегодня + предыдущий календарный день)

Таким образом, результат будет следующим:

    +---------+--------+--------+-------------+------------------+
    | user_id | amount |  date  | sum_per_day | sum_over_two_day |
    +---------+--------+--------+-------------+------------------+
    | user8   |   300  | 7/2/20 |     300     |       700        |
    | user8   |   150  | 6/2/20 |     400     |       500        |
    | user8   |   250  | 6/2/20 |     400     |       500        |
    | user8   |   25   | 5/2/20 |     100     |       100        |
    | user8   |   25   | 5/2/20 |     100     |       100        |
    | user8   |   25   | 5/2/20 |     100     |       100        |
    | user8   |   25   | 5/2/20 |     100     |       100        |
    | user8   |   50   | 2/2/20 |     50      |       50         |
    +---------+--------+--------+-------------+------------------+

Ответы [ 2 ]

7 голосов
/ 28 мая 2020

Правильный способ - использовать оконную функцию с предложением RANGE:

SELECT user_id,
       amount,
       date,
       sum(amount) OVER (PARTITION BY user_id
                         ORDER BY date
                         RANGE BETWEEN INTERVAL '1 day' PRECEDING
                               AND CURRENT ROW)
          AS sum_over_two_day
FROM atable
ORDER BY user_id, date;

 user_id | amount |    date    | sum_over_two_day 
---------+--------+------------+------------------
 user8   |     50 | 2020-02-02 |               50
 user8   |     25 | 2020-02-05 |              100
 user8   |     25 | 2020-02-05 |              100
 user8   |     25 | 2020-02-05 |              100
 user8   |     25 | 2020-02-05 |              100
 user8   |    250 | 2020-02-06 |              500
 user8   |    150 | 2020-02-06 |              500
 user8   |    300 | 2020-02-07 |              700
(8 rows)
2 голосов
/ 28 мая 2020

Попробуйте этот обходной путь для своей проблемы:

select 
t1.user_id, 
t1.amount,
date(t1.date_),
(select sum(amount)  from tab where user_id=t1.user_id and date_=t1.date_ ),
(select sum(amount)  from tab where user_id=t1.user_id and date_ between t1.date_-1 and t1.date_ )  
from tab t1

с функцией окна для первой суммы

select 
t1.user_id, 
t1.amount,
date(t1.date_),
sum(t1.amount) over (partition by t1.user_id,t1.date_),
(select sum(amount)  from tab where user_id=t1.user_id and date_ between t1.date_-1 and t1.date_ )
from tab t1

см. ДЕМО

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...