【问题标题】:PostgreSQL - Referencing another aggregate column in a window functionPostgreSQL - 在窗口函数中引用另一个聚合列
【发布时间】:2014-05-29 22:03:34
【问题描述】:

这是查询:

SELECT name,
       group_name,
       number1, -- associated with either the name or the group_name
       number2,
       ...
       (number1 * number2) - SUM(number3) AS total_difference,
       SUM(total_difference) OVER (PARTITION BY group_name) AS grand_total
FROM t
GROUP BY name,
         group_name,
         number1,
         number2,
         ...;

单个 group_name 可能有许多关联名称。

为每个名称生成total_difference。我的目标是让 grand_total 成为 group_name 中每个名称的 total_difference 之和。使用 number1 到 numberx 为每个名称计算 total_difference,其中一些与名称相关,一些与 group_name 相关。这是一个示例表(忽略数学,这些数字显然只是编造的):

name | group_name | number1 | number2 | number3 | total_difference | grand_total
-----+------------+---------+---------+---------+------------------+-------------
Fred | A          | 3       | 67      | 2       | 10               | 30
Amy  | A          | 5       | 25      | 45      | 20               | 30
Jim  | B          | 8       | 33      | 15      | 30               | 100
Tom  | B          | 2       | 6       | 35      | 45               | 100
Al   | B          | 6       | 89      | 4       | 25               | 100
...

问题是我在创建grand_total 时显然不能引用total_difference,因为它还不存在。我也不能只复制数学:

SELECT ...
       SUM((number1 * number2) - SUM(number3)) OVER (PARTITION BY group_name) AS grand_total
...

因为那样我会有两个不同的聚合函数,它们具有不同的 group by 参数(我尝试嵌套窗口函数,但在收到错误消息之前我就知道这是一个愚蠢的想法)。

我知道我可以制作表格并在之后执行连接,我完全没有问题这样做。但是,我看不到这个让我很困扰......这更像是一种学习体验。

我怎样才能实现我的目标。我什至需要一个窗口功能?这甚至可能吗?

此表仅供演示之用,仅供参考。我正在使用 PostgreSQL 9.3。

【问题讨论】:

  • 您的 Postgres 版本和表定义应该在问题中。

标签: sql postgresql window-functions


【解决方案1】:

认为你所追求的是聚合函数之上的窗口函数,这是完全可能的,因为窗口函数是在聚合之后应用的

SELECT name
     , group_name
     , number1
     , number2
     , (number1 * number2) - SUM(number3) AS total_difference
     , SUM((number1 * number2) - SUM(number3)) OVER (PARTITION BY group_name) AS grand_total
FROM   t
GROUP  BY name, group_name, number1, number2;

在窗口函数内重复聚合函数。另一种方法是像@Gordon posted 这样的子查询。但是请注意,他帖子中的第一个查询目前与第二个不匹配。

更多解释的相关答案:

【讨论】:

    【解决方案2】:

    你试过了吗?

    SELECT ...
           (SUM(number1 * number2) OVER (PARTITION BY group_name) -
            SUM(SUM(number3)) OVER (PARTITION BY group_name)
           ) as grand_total
    

    另一种方法是使用子查询:

    SELECT t.*, SUM(total_difference) OVER (PARTITION BY group_name) AS grand_total
    FROM (SELECT name, group_name, number1, number2,
                 ...
                 (number1 * number2) - SUM(number3) AS total_difference
          FROM t
          GROUP BY name, group_name, number1, number2, ...
         ) t
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-09
      • 1970-01-01
      • 2016-07-04
      • 1970-01-01
      • 2013-07-10
      • 2021-02-14
      • 2018-01-16
      • 2018-08-12
      相关资源
      最近更新 更多