PostgreSQL,同时有两个窗口函数

时间:2016-08-10 06:45:22

标签: postgresql window-functions

我有典型的数据表,比如mytemptable

DROP TABLE IF EXISTS mytemptable; 
CREATE TEMP TABLE mytemptable 
       (mydate date, somedoc text, inqty int, outqty int); 
INSERT INTO mytemptable (mydate, somedoc, inqty, outqty) 
VALUES ('01.01.2016.', '123-13-24', 3, 0), 
       ('04.01.2016.', '15-19-44',  2, 0), 
       ('06.02.2016.', '15-25-21',  0, 1), 
       ('04.01.2016.', '21-133-12', 0, 1), 
       ('04.01.2016.', '215-11-51', 0, 2), 
       ('05.01.2016.', '11-181-01', 0, 1), 
       ('05.02.2016.', '151-80-8',  4, 0), 
       ('04.01.2016.', '215-11-51', 0, 2), 
       ('07.02.2016.', '34-02-02',  0, 2); 

SELECT row_number() OVER(ORDER BY mydate) AS rn, 
       mydate, somedoc, inqty, outqty, 
       SUM(inqty-outqty) OVER(ORDER BY mydate) AS csum 
  FROM mytemptable 
 ORDER BY mydate; 

在我的SELECT查询中,我尝试按日期排序结果并添加行号'rn'和累计(传递)sum'csum'。当然没有成功。
我相信这是因为我在查询中使用了两个窗口函数,这些函数在某些方面存在冲突。

如何正确地使此查询快速,有序并在'csum'列中获得正确的结果(3,5,4,2,0,-1,3,2,0)

1 个答案:

答案 0 :(得分:2)

由于在2016-04-01处存在排序关系,因此这些行的结果将是累计总和。如果您希望它不同,请使用order by中的解开列。

From the manual

  

还有另一个与窗口函数相关的重要概念:对于每一行,在其分区中有一组称为窗口框架的行。许多(但不是全部)窗口函数仅作用于窗口框架的行,而不是整个分区。默认情况下,如果提供ORDER BY,则该帧包含从分区开始到当前行的所有行,以及根据ORDER BY子句等于当前行的任何后续行。省略ORDER BY时,默认框架由分区中的所有行组成

如果没有解开的列,您可以在外部查询中使用生成的行号:

set datestyle = 'dmy';
with mytemptable (mydate, somedoc, inqty, outqty) as (
    values
    ('01-01-2016'::date, '123-13-24', 3, 0), 
    ('04-01-2016', '15-19-44',  2, 0), 
    ('06-02-2016', '15-25-21',  0, 1), 
    ('04-01-2016', '21-133-12', 0, 1), 
    ('04-01-2016', '215-11-51', 0, 2), 
    ('05-01-2016', '11-181-01', 0, 1), 
    ('05-02-2016', '151-80-8',  4, 0), 
    ('04-01-2016', '215-11-51', 0, 2), 
    ('07-02-2016', '34-02-02',  0, 2)
)
select *, sum(inqty-outqty) over(order by mydate, rn) as csum
from (
    select
        row_number() over(order by mydate) as rn, 
        mydate, somedoc, inqty, outqty
    from mytemptable
) s
order by mydate;
 rn |   mydate   |  somedoc  | inqty | outqty | csum 
----+------------+-----------+-------+--------+------
  1 | 2016-01-01 | 123-13-24 |     3 |      0 |    3
  2 | 2016-04-01 | 15-19-44  |     2 |      0 |    5
  3 | 2016-04-01 | 21-133-12 |     0 |      1 |    4
  4 | 2016-04-01 | 215-11-51 |     0 |      2 |    2
  5 | 2016-04-01 | 215-11-51 |     0 |      2 |    0
  6 | 2016-05-01 | 11-181-01 |     0 |      1 |   -1
  7 | 2016-05-02 | 151-80-8  |     4 |      0 |    3
  8 | 2016-06-02 | 15-25-21  |     0 |      1 |    2
  9 | 2016-07-02 | 34-02-02  |     0 |      2 |    0