Sql 按id和月份的累计金额(以Presto为单位)
在亚马逊雅典娜,我有一张这样的桌子:Sql 按id和月份的累计金额(以Presto为单位),sql,amazon-athena,presto,Sql,Amazon Athena,Presto,在亚马逊雅典娜,我有一张这样的桌子: 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 1
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
所以我想知道每个月最后一天每个ID在月底的累计金额。我知道如何逐月进行,但不是一次查询
另一个问题是填充空月份,即ID 1没有所有月份的条目,因此必须重新使用累积总和
如果有MySQL的解决方案,我也会很感激
我希望这是有意义的,并提前表示感谢 这里有一个MySQL 8+解决方案,但是它可以很容易地适应早期版本,或者其他支持CTE的数据库。它使用日历表来显示id值和日期。在生成跨月/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;
在MySQL的早期版本或PrestoDB上实现上述功能的主要挑战在于是否可能删除CTE,以及日期函数逻辑。除此之外,查询应保持不变。您可以在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中不起作用。第二个可能会有更糟糕的性能。通过重写一点,我成功地获得了我在Presto中想要的结果。我添加了一个更加动态的日期范围,所有ID都是250000,我似乎很快就得到了一个合适的结果。