【问题标题】:Get running total per month and year from PostgreSQL database从 PostgreSQL 数据库获取每月和每年的运行总计
【发布时间】:2018-06-17 09:20:05
【问题描述】:

这是我的示例数据(表“sumtest”):

+-------+--------+-------+
| month |  value |  year |
+-------+--------+-------+
|     1 |     10 |  2017 |
|     2 |      0 |  2017 |
|     2 |     10 |  2016 |  # note: different year
|     2 |      5 |  2017 |
|     3 |     88 |  2017 |
|     3 |      2 |  2017 |
|     5 |      1 |  2017 |
|     5 |      4 |  2017 |
|     5 |      5 |  2017 |
+-------+--------+-------+

我想获得每个月的总值,以及该特定月份每年的运行总值,即我希望我的结果是这样的:

+------+-------+-----------+----------+
| year | month | sum_month | sum_year |
+------+-------+-----------+----------+
| 2016 |     2 |        10 |       10 |
| 2017 |     1 |        10 |       10 |
| 2017 |     2 |         5 |       15 |
| 2017 |     3 |        90 |      105 |
| 2017 |     5 |        10 |      115 |
+------+-------+-----------+----------+

我是 Postgres 的新手,我尝试了以下方法:

    SELECT *, sum(value) OVER (PARTITION BY month, year) AS sum_month, 
sum(value) OVER (PARTITION BY year) AS sum_year
    FROM sumtest
    ORDER BY year, month

但这会为每个原始条目生成一行,并且每行列出的年度总和而不是到目前为止的累积总和:

+-------+-------+------+-----------+----------+
| month | value | year | sum_month | sum_year |
+-------+-------+------+-----------+----------+
|     2 |    10 | 2016 | '10'      | '10'     |
|     1 |    10 | 2017 | '10'      | '115'    |
|     2 |     5 | 2017 | '5'       | '115'    |
|     2 |     0 | 2017 | '5'       | '115'    |
|     3 |     2 | 2017 | '90'      | '115'    |
|     3 |    88 | 2017 | '90'      | '115'    |
|     5 |     4 | 2017 | '10'      | '115'    |
|     5 |     1 | 2017 | '10'      | '115'    |
|     5 |     5 | 2017 | '10'      | '115'    |
+-------+-------+------+-----------+----------+

我也尝试过使用 GROUP BY,它适用于月份的累积总和,但我现在没有如何包括一年的运行总计(因为不应该按月份分组)。

任何帮助将不胜感激。

【问题讨论】:

标签: sql postgresql window-functions cumulative-sum


【解决方案1】:

您可以在查询上方添加MAXGROUP BY,同时在OVER() 中添加ORDER BY

select year,month,MAX( sum_month) sum_month,  MAX(sum_year) sum_year 
FROM
(
 SELECT *, sum(value) OVER (PARTITION BY month, year ORDER BY year,month) AS sum_month, 
sum(value) OVER (PARTITION BY year ORDER BY year,month) AS sum_year
    FROM sumtest
)  a
GROUP BY year,month;

DEMO

【讨论】:

  • 效果很好,谢谢!还有一个问题:为什么在 OVER() 中需要 ORDER BY?谢谢。
  • @canavanin:当你说运行总和时,你需要一个方向来运行,不是吗?因此 Order by 指定了评估聚合 (SUM) 的顺序。如果不指定窗口子句之间的ROWS,则order by的默认值是running sum
【解决方案2】:

准备:

t=# create table s(a text,m int, v int, y int, b text);
CREATE TABLE
t=# copy s from stdin delimiter '|';
>> \.
COPY 9
t=# alter table s drop column a;
ALTER TABLE
t=# alter table s drop column b;
ALTER TABLE

查询:

t=# select distinct y,m,sum(v) over (partition by m,y), sum(v) over (partition by y order by m) from s order by y,m;
  y   | m | sum | sum
------+---+-----+-----
 2016 | 2 |  10 |  10
 2017 | 1 |  10 |  10
 2017 | 2 |   5 |  15
 2017 | 3 |  90 | 105
 2017 | 5 |  10 | 115
(5 rows)

更新 - 我完全错过了累积

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-24
    • 1970-01-01
    • 2019-03-07
    • 2017-11-14
    • 1970-01-01
    相关资源
    最近更新 更多