每月计算 运行 总计
Calculate running total per month
假设我有这个 table:
id; date; units
1; Jan 1; 1
2; Jan 2; 4
3; Feb 9; 6
4; Mar 1; 1
5; Mar 4; 2
我现在如何相应地计算 "accumulated_month" 列?计算应在每个新月重新开始。
id; date; units; accumulated_month
1; Jan 1; 1; 1
2; Jan 2; 4; 5
3; Feb 9; 6; 6
4; Mar 1; 1; 1
5; Mar 4; 2; 3
我得到的只有这个:
id; date; units; accumulated_month
1; Jan 1; 1; 5
2; Jan 2; 4; 5
3; Feb 9; 6; 6
4; Mar 1; 1; 3
5; Mar 4; 2; 3
create table t (id int, date date, units int);
insert into t (id, date, units) values
(1, '2016-01-01', 1),
(2, '2016-01-02', 4),
(3, '2016-02-09', 6),
(4, '2016-03-01', 1),
(5, '2016-03-04', 2);
不清楚您是想要月总计还是月内的 运行 总计。本月总计:
select
id, date, units,
sum(units) over (partition by date_trunc('month', date)) as acumm
from t
order by 1,2
;
id | date | units | acumm
----+------------+-------+-------
1 | 2016-01-01 | 1 | 5
2 | 2016-01-02 | 4 | 5
3 | 2016-02-09 | 6 | 6
4 | 2016-03-01 | 1 | 3
5 | 2016-03-04 | 2 | 3
如果您想在一个月内获得 运行 总数,请将订单添加到 window 函数:
select
id, date, units,
sum(units) over (
partition by date_trunc('month', date)
order by id
) as acumm
from t
order by 1,2
;
id | date | units | acumm
----+------------+-------+-------
1 | 2016-01-01 | 1 | 1
2 | 2016-01-02 | 4 | 5
3 | 2016-02-09 | 6 | 6
4 | 2016-03-01 | 1 | 1
5 | 2016-03-04 | 2 | 3
运行这个:
SELECT
t1.id,
t1.date,
t1.units,
SUM(t2.units) accumulated_month
FROM t t1
JOIN t t2
ON date_trunc('month', t1.date) = date_trunc('month', t2.date)
AND t2.date <= t1.date
GROUP BY t1.id, t1.date, t1.units
ORDER BY t1.id
编辑:
简化SQL:
SELECT
t1.*, SUM(t2.units) accumulated_month
FROM t t1
JOIN t t2
ON date_trunc('month', t1.date) = date_trunc('month', t2.date)
AND t2.date <= t1.date
GROUP BY t1.id
ORDER BY t1.id
逻辑
背后的逻辑是JOIN
table 本身。然后对于 t1
JOIN
的每一行,t2
中的所有行都满足 (AND
):
- 一样year/month
- t2.date <= t1.date
有了这些 ON
约束,t1
中的每一行将 JOIN
累积到那个月为止。所以如果不分组,你会得到类似的东西:
╔════╦════════════╦═══════╦════════════╦══════════╗
║ id ║ date ║ units ║ t2_date ║ t2_units ║
╠════╬════════════╬═══════╬════════════╬══════════╣
║ 1 ║ 2016-01-01 ║ 1 ║ 2016-01-01 ║ 1 ║
║ 2 ║ 2016-01-02 ║ 4 ║ 2016-01-01 ║ 1 ║
║ 2 ║ 2016-01-02 ║ 4 ║ 2016-01-02 ║ 4 ║
║ 3 ║ 2016-02-09 ║ 6 ║ 2016-02-09 ║ 6 ║
║ 4 ║ 2016-03-01 ║ 1 ║ 2016-03-01 ║ 1 ║
║ 5 ║ 2016-03-04 ║ 2 ║ 2016-03-01 ║ 1 ║
║ 5 ║ 2016-03-04 ║ 2 ║ 2016-03-04 ║ 2 ║
╚════╩════════════╩═══════╩════════════╩══════════╝
在 GROUP BY t1.id
之后,您可以 SUM(t2.units)
得到您期望的结果。
假设我有这个 table:
id; date; units
1; Jan 1; 1
2; Jan 2; 4
3; Feb 9; 6
4; Mar 1; 1
5; Mar 4; 2
我现在如何相应地计算 "accumulated_month" 列?计算应在每个新月重新开始。
id; date; units; accumulated_month
1; Jan 1; 1; 1
2; Jan 2; 4; 5
3; Feb 9; 6; 6
4; Mar 1; 1; 1
5; Mar 4; 2; 3
我得到的只有这个:
id; date; units; accumulated_month
1; Jan 1; 1; 5
2; Jan 2; 4; 5
3; Feb 9; 6; 6
4; Mar 1; 1; 3
5; Mar 4; 2; 3
create table t (id int, date date, units int);
insert into t (id, date, units) values
(1, '2016-01-01', 1),
(2, '2016-01-02', 4),
(3, '2016-02-09', 6),
(4, '2016-03-01', 1),
(5, '2016-03-04', 2);
不清楚您是想要月总计还是月内的 运行 总计。本月总计:
select
id, date, units,
sum(units) over (partition by date_trunc('month', date)) as acumm
from t
order by 1,2
;
id | date | units | acumm
----+------------+-------+-------
1 | 2016-01-01 | 1 | 5
2 | 2016-01-02 | 4 | 5
3 | 2016-02-09 | 6 | 6
4 | 2016-03-01 | 1 | 3
5 | 2016-03-04 | 2 | 3
如果您想在一个月内获得 运行 总数,请将订单添加到 window 函数:
select
id, date, units,
sum(units) over (
partition by date_trunc('month', date)
order by id
) as acumm
from t
order by 1,2
;
id | date | units | acumm
----+------------+-------+-------
1 | 2016-01-01 | 1 | 1
2 | 2016-01-02 | 4 | 5
3 | 2016-02-09 | 6 | 6
4 | 2016-03-01 | 1 | 1
5 | 2016-03-04 | 2 | 3
运行这个:
SELECT
t1.id,
t1.date,
t1.units,
SUM(t2.units) accumulated_month
FROM t t1
JOIN t t2
ON date_trunc('month', t1.date) = date_trunc('month', t2.date)
AND t2.date <= t1.date
GROUP BY t1.id, t1.date, t1.units
ORDER BY t1.id
编辑:
简化SQL:
SELECT
t1.*, SUM(t2.units) accumulated_month
FROM t t1
JOIN t t2
ON date_trunc('month', t1.date) = date_trunc('month', t2.date)
AND t2.date <= t1.date
GROUP BY t1.id
ORDER BY t1.id
逻辑
背后的逻辑是JOIN
table 本身。然后对于 t1
JOIN
的每一行,t2
中的所有行都满足 (AND
):
- 一样year/month
- t2.date <= t1.date
有了这些 ON
约束,t1
中的每一行将 JOIN
累积到那个月为止。所以如果不分组,你会得到类似的东西:
╔════╦════════════╦═══════╦════════════╦══════════╗
║ id ║ date ║ units ║ t2_date ║ t2_units ║
╠════╬════════════╬═══════╬════════════╬══════════╣
║ 1 ║ 2016-01-01 ║ 1 ║ 2016-01-01 ║ 1 ║
║ 2 ║ 2016-01-02 ║ 4 ║ 2016-01-01 ║ 1 ║
║ 2 ║ 2016-01-02 ║ 4 ║ 2016-01-02 ║ 4 ║
║ 3 ║ 2016-02-09 ║ 6 ║ 2016-02-09 ║ 6 ║
║ 4 ║ 2016-03-01 ║ 1 ║ 2016-03-01 ║ 1 ║
║ 5 ║ 2016-03-04 ║ 2 ║ 2016-03-01 ║ 1 ║
║ 5 ║ 2016-03-04 ║ 2 ║ 2016-03-04 ║ 2 ║
╚════╩════════════╩═══════╩════════════╩══════════╝
在 GROUP BY t1.id
之后,您可以 SUM(t2.units)
得到您期望的结果。