棘手的SQL组由sql查询与运行总和

时间:2014-08-12 21:52:09

标签: sql postgresql group-by aggregate-functions window-functions

我正在处理一个查询,该查询生成按createdtype分组的大小列的运行总和,并且还会考虑deleted日期。所以我并不仅仅意味着该日期的总和,而是一笔运行金额。如果我周一把一个苹果放在桶里(星期一= 1)。如果我在星期二再放一个苹果(星期二= 2),... 我只是对如何开始感到难过。

以下是一些示例数据:

[id,type, size, created, deleted]  
1,A,    2,  2014-08-05, 2014-08-06  
2,A,    3,  2014-08-05,   
3,A,    5,  2014-08-06,       
4,A,    4,  2014-08-06,      
5,B,    2,  2014-08-06, 2014-08-06  
6,B,    4,  2014-08-07, 2014-08-07  
7,C,    6,  2014-08-07, 2014-08-07  
8,C,    4,  2014-08-07,       
9,D,    3,  2014-08-07,       
10,E,   5,  2014-08-07,       
11,C,   6,  2014-08-07,       

结果应如下所示:

[Date, Type, Sum]  
2014-08-05,A,5  (sum of IDs 1,2)  
2014-08-06,A,14 (sum of IDs 1,2,3,4)  
2014-08-06,B,2  
2014-08-07,A,11 (sum of IDs 2,3,4: Notice that ID 1 is not included because it was deleted 2014-08-06)  
2014-08-07,B,6 (sum of IDs 5,6)  
2014-08-07,C,16 (sum of IDs 7,8,11)  
etc...

1 个答案:

答案 0 :(得分:0)

SELECT DISTINCT day, type
     , sum(size) OVER (PARTITION BY type ORDER BY day) AS running_total
FROM (
   SELECT created AS day, type, size
   FROM   tbl

   UNION  ALL
   SELECT deleted, type, size * -1
   FROM   tbl
   WHERE  deleted IS NOT NULL
   ) sub
ORDER BY 1,2;

返回:

day         type  running_total
-------------------------------
2014-08-05  A     5
2014-08-06  A     12
2014-08-06  B     0
2014-08-07  B     0
2014-08-07  C     10
2014-08-07  D     3
2014-08-07  E     5

说明:

  • 按照(created, type)给出的每一行和数字。
  • 对已删除该行的(deleted, type)执行相同的操作。
  • 使用窗口聚合函数sum() OVER ...
  • 计算运行总计
  • 由于每天可以生成多个相同的行,因此请DISTINCT应用折叠。

如果删除仅在第二天生效,只需在deleted日期添加1:

...
   SELECT deleted + 1, type, size * -1
...

更快

结果相同,更详细,但更快:

SELECT day, type
     , sum(daily_delta) OVER (PARTITION BY type ORDER BY day) AS running_total
FROM  (
    SELECT day, type, sum(size) AS daily_delta
    FROM (
        SELECT created AS day, type, size
        FROM   tbl

        UNION  ALL
        SELECT deleted, type, size * -1
        FROM   tbl
        WHERE  deleted IS NOT NULL
        ) sub
    GROUP  BY  1,2
    ) sub
ORDER BY 1,2;

详细解释

密切相关的答案

SQL Fiddle.