计算PostgreSQL中的累积和

时间:2014-04-03 14:47:29

标签: sql postgresql window-functions analytic-functions cumulative-sum

我想找到累积或运行的字段数量,并将其从分段插入表格。我的暂存结构是这样的:

ea_month    id       amount    ea_year    circle_id
April       92570    1000      2014        1
April       92571    3000      2014        2
April       92572    2000      2014        3
March       92573    3000      2014        1
March       92574    2500      2014        2
March       92575    3750      2014        3
February    92576    2000      2014        1
February    92577    2500      2014        2
February    92578    1450      2014        3          

我希望我的目标表看起来像这样:

ea_month    id       amount    ea_year    circle_id    cum_amt
February    92576    1000      2014        1           1000 
March       92573    3000      2014        1           4000
April       92570    2000      2014        1           6000
February    92577    3000      2014        2           3000
March       92574    2500      2014        2           5500
April       92571    3750      2014        2           9250
February    92578    2000      2014        3           2000
March       92575    2500      2014        3           4500
April       92572    1450      2014        3           5950

我对如何实现这一结果非常困惑。我想用PostgreSQL实现这个结果。

有人可以建议如何实现这个结果集吗?

1 个答案:

答案 0 :(得分:91)

基本上,你需要window function。这是当今的标准功能。除了正版窗口函数之外,您还可以通过附加OVER子句将任何聚合函数用作Postgres中的窗口函数。

这里的特殊困难是让分区和排序顺序正确:

SELECT ea_month, id, amount, ea_year, circle_id
     , sum(amount) OVER (PARTITION BY circle_id ORDER BY ea_year, ea_month) AS cum_amt
FROM   tbl
ORDER  BY circle_id, month;

此处 GROUP BY

每行的总和是从分区的第一行到当前行计算的 - 或准确引用the manual

  

默认框架选项为RANGE UNBOUNDED PRECEDING,即   与RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW相同。同   ORDER BY,这会将框架设置为分区中的所有行   从当前行的ORDER BY对等开始。

...这是您追求的累积或运行金额。大胆强调我的。

此查询中具有相同(circle_id, ea_year, ea_month)的行是" peer" 。所有这些都显示相同的运行总和,所有对等项都添加到总和中。但我假设你的表在UNIQUE上是(circle_id, ea_year, ea_month),那么排序顺序是确定性的,没有行有对等。

现在,ORDER BY ... ea_month 无法使用月份名称的字符串 。 Postgres将根据区域设置按字母顺序排序。

如果您的表中存储了实际的date值,则可以正确排序。如果没有,我建议将[{1}}和ea_year替换为表格中date类型的ea_month列。

  • 使用to_date()转换您的内容:

    mon
  • 要显示,您可以使用to_char()获得原始字符串:

    to_date(ea_year || ea_month , 'YYYYMonth') AS mon
    

虽然坚持不幸的布局,但这将有效:

to_char(mon, 'Month') AS ea_month
to_char(mon, 'YYYY') AS ea_year