2016-03-09 89 views
1

我试图从用户分数条目列表中获得总计用户分数的排行榜。单个用户在此表中可以有多个条目。PostgreSQL窗口函数“列必须出现在GROUP BY子句中”

我有如下表:

rewards 
======= 
user_id | amount 

我想补充了所有的amount值的给定用户,然后对他们进行排名,在全球排行榜。下面是我试图运行查询:

SELECT user_id, SUM(amount) AS score, rank() OVER (PARTITION BY user_id) FROM rewards;

,我发现了以下错误:

ERROR: column "rewards.user_id" must appear in the GROUP BY clause or be used in an aggregate function 
LINE 1: SELECT user_id, SUM(amount) AS score, rank() OVER (PARTITION... 

是不是user_id已经在一个“聚合函数”,因为我想对其进行分区? PostgreSQL的手册显示以下条目,我觉得是我的直接并联,所以我不知道为什么我的不工作:

SELECT depname, empno, salary, avg(salary) OVER (PARTITION BY depname) FROM empsalary;

他们不是depname分组,怎么让他们的作品?

例如,对于如下的数据:

user_id | score 
=============== 
1 | 2 
1 | 3 
2 | 5 
3 | 1 

我期望以下输出(I都作了 “扎” 用户1之间和2):

user_id | SUM(score) | rank 
=========================== 
1 | 5 | 1 
2 | 5 | 1 
3 | 1 | 3 

所以用户1总分为5,并且排名第一,用户2与分数为5并且因此也是排名第一,并且用户3排名第三,得分为1.

+0

你想要什么结果? –

+0

@JuanCarlosOropeza增加了一些细节。 – aardvarkk

回答

3

您需要GROUP BY USER_ID,因为它没有被聚合。然后你可以按照你想要的降序排列SUM(score);

SQL Fiddle Demo

SELECT user_id, SUM(score), RANK() OVER (ORDER BY SUM(score) DESC) 
FROM rewards 
GROUP BY user_id; 

user_id | sum | rank 
---------+-----+------ 
     1 | 5 | 1 
     2 | 5 | 1 
     3 | 1 | 3 
+0

这看起来是最简单和最直接的方法。我想我需要提高我对“PARTITION BY”的确切含义的理解。谢谢你的帮助! – aardvarkk

+0

“PARTITION BY”对每一行都起着“GROUP BY”的作用。在这种情况下,您需要'GROUP BY',因为您从4行开始并以3结尾。在问题情况下,如果您删除了SUM(),那么windows函数将返回所有4行 –

1

如果您有

SELECT user_id, SUM(amount) .... 
        ^^^ 
        agreagted function (not window function) 
    .... 
    FROM ..... 

你需要

GROUP BY user_id 
+0

如果我按user_id进行分组,他们全部排在第一位。分区有效地将它们分组,对吗?我不明白这应该如何工作? – aardvarkk

+0

对不起,我只是回答什么是错的。我现在正在测试正确的方法:P –

2

有窗口函数与聚集函数之间的差。某些函数既可以用作窗口函数又可以用作聚合函数,这可能会导致混淆。窗口函数可以被查询中的OVER子句识别。

然后,您的案例中的查询将变为,首先在user_id上进行聚合,然后在total_amount上执行窗口函数。

SELECT user_id, total_amount, RANK() OVER (ORDER BY total_amount DESC) FROM ( SELECT user_id, SUM(amount) total_amount FROM table GROUP BY user_id ) q ORDER BY total_amount DESC

相关问题