Накопленная сумма по id и по месяцам в Presto - PullRequest
0 голосов
/ 11 октября 2018

В Amazon Athena у меня есть таблица, которая выглядит следующим образом:

id   amount date
1    100    2018-04-05
1    50     2018-06-18
2    10     2018-04-23
2    100    2018-04-28
2    50     2018-07-07
2    10     2018-08-08

И я хотел бы получить такой результат, как

id   cum_sum date
1    100    2018-04
1    100    2018-05
1    150    2018-06
1    150    2018-07
1    150    2018-08
2    110    2018-04
2    110    2018-05
2    110    2018-06 
2    160    2018-07
2    170    2018-08

Поэтому я хотел бы получить кумулятивную суммуза идентификатор за конец месяца (последний день месяца).Я знаю, как это сделать месяц за месяцем, но не в одном запросе.

Другая проблема также заключается в заполнении пустых месяцев (т. Е. В идентификаторе 1 нет записей за все месяцы, поэтому совокупную сумму просто необходимо использовать повторно).

Если есть решение и для MySQL, я тоже буду признателен.

Надеюсь, это имеет смысл, и спасибо заранее.

Ответы [ 2 ]

0 голосов
/ 11 октября 2018

Вы можете использовать оконные функции в PrestoDB.Вы можете генерировать даты.Также достаточно просто перечислить их:

with months as (
      selecct '2018-04-01' as yyyy_mm union all    -- use the first of the month
      select '2018-05-01' union all
      select '2018-06-01' union all
      select '2018-07-01' union all
      select '2018-08-01'
     )
select i.id, m.yyyy_mm, sum(t.amt) as month_amount,
       sum(sum(t.amt)) over (partition by i.id order by m.yyyy_mm) as cumulative_amt
from (select distinct id from t) i cross join
     months m left join
     t
     on t.id = i.id and
        t.date >= m.yyyy_mm and
        t.date < m.yyyy_mm + interval '1 day'
group by i.id, m.yyyy_mm
order by i.id, m.yyyy_mm;

Это также должно работать в MySQL 8.0.В более ранних версиях вам понадобились бы переменные или коррелированный подзапрос.Первый не будет работать в PrestoDB.Второй может иметь гораздо худшую производительность.

0 голосов
/ 11 октября 2018

Вот решение MySQL 8+, которое, однако, можно легко адаптировать к более ранним версиям или к другой базе данных, которая поддерживает CTE.Используются календарные таблицы для значений и дат id.После генерации сумм по месяцам / идентификаторам он затем накапливает сумму для получения окончательного результата.

WITH ids AS (
    SELECT 1 AS id FROM dual UNION ALL
    SELECT 2 FROM dual
),
months AS (
    SELECT '2018-04-01' AS month UNION ALL    -- use the first of the month
    SELECT '2018-05-01' UNION ALL             -- to represent a given month
    SELECT '2018-06-01' UNION ALL
    SELECT '2018-07-01' UNION ALL
    SELECT '2018-08-01'
),
cte AS (
    SELECT
        i.id,
        m.month,
        SUM(amount) AS amount
    FROM ids i
    CROSS JOIN months m
    LEFT JOIN yourTable t
        ON t.id = i.id AND
           t.date >= m.month AND t.date < DATE_ADD(m.month, INTERVAL 1 MONTH)
    GROUP BY
        i.id,
        m.month
)

SELECT
    id,
    (SELECT SUM(t2.amount) FROM cte t2
     WHERE t1.id = t2.id AND t2.month <= t1.month) cum_sum,
    DATE_FORMAT(month, '%Y-%m') AS date
FROM cte t1
ORDER BY
    id,
    month;

enter image description here

Демо

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

...