PostgreSQL - 在窗口函数中引用另一个聚合列

时间:2014-04-15 13:45:43

标签: sql postgresql window-functions

以下是查询:

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
...

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

我知道我之后可以制作表格并进行连接,这样做完全没有问题。但是,让我感到困扰的是我无法看到这一点......这比任何事情都更像是一种学习经历。

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

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

2 个答案:

答案 0 :(得分:3)

认为你所拥有的是一个聚合函数的窗口函数,这完全可能,因为在聚合之后应用了窗口函数:

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这样的子查询。但请注意,他帖子中的第一个查询目前与第二个查询不匹配。

相关答案以及更多解释:

答案 1 :(得分:0)

你试过这个吗?

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