PostgreSQL:如何在周表中查找具有max money的id

PostgreSQL:如何在周表中查找具有max money的id,sql,postgresql,Sql,Postgresql,我持有每周锦标赛的虚拟资金,如下表所示: # select * from pref_money limit 5; id | money | yw ----------------+-------+--------- OK32378280203 | -27 | 2010-44 OK274037315447 | -56 | 2010-44 OK19644992852 | 8 | 2010-44 OK21807961329 | 114 |

我持有每周锦标赛的虚拟资金,如下表所示:

# select * from pref_money limit 5;
       id       | money |   yw
----------------+-------+---------
 OK32378280203  |   -27 | 2010-44
 OK274037315447 |   -56 | 2010-44
 OK19644992852  |     8 | 2010-44
 OK21807961329  |   114 | 2010-44
 FB1845091917   |   774 | 2010-44
(5 rows)
在我列出用户的PHP脚本中,我需要知道谁是每周的赢家,这样我就可以在他们的名字附近显示奖牌。因此,我尝试以下SQL语句:

# find the weekly winners
$sth = $db->prepare('select id from pref_money 
    where money in 
    (select max(money) from pref_money group by yw)');

$sth->execute();
while ($row = $sth->fetch(PDO::FETCH_ASSOC))
        @$medals[$row['id']]++;
这通常是有效的,但有时我会得到误报,当一个用户碰巧在某个星期拥有与另一个星期的赢家一样多的钱,但不是最大的

有没有人知道如何更改SQL语句,以便只选择赢家ID

当我尝试以下操作时,我得到一个错误:

# select id, max(money) from pref_money group by yw;
ERROR:  column "pref_money.id" must appear in the 
  GROUP BY clause or be used in an aggregate function
谢谢大家!! 亚历克斯


更新:PostgreSQL 8.4.5/CentOS,可能有联系:-

哪个版本的PostgreSQL?使用8.4中引入的窗口功能,这很容易:

select id, yw from (
    select id,
           yw,
           row_number() over(partition by yw order by money desc) as ranking
    from pref_money
) x
where x.ranking = 1
这在旧版本中几乎可以做到:

select id, yw
from pref_money
     join (select yw, max(money) max_money
           from pref_money
           group by yw) max_money
          on pref_money.yw = max_money.yw and pref_money.money = max_money.max_money

但请注意,如果两个用户为获得最高收入而结对,则输出将显示两次。如果这是您真正想要的,您也可以使用窗口功能,使用rank而不是row_number

假设PostgreSQL 8.4+,并且在给定的一周内没有人联系到赢家位置-这将列出每周的赢家:

WITH sample AS (
  SELECT t.id,
         t.yw,
         ROW_NUMBER() OVER(PARTITION BY t.yw
                               ORDER BY t.money DESC) AS rank
    FROM PREF_MONEY t)
SELECT s.id
  FROM sample s
 WHERE s.rank = 1
如果可以系领带,请使用:

WITH sample AS (
  SELECT t.id,
         t.yw,
         DENSE_RANK() OVER(PARTITION BY t.yw
                               ORDER BY t.money DESC) AS rank
    FROM PREF_MONEY t)
SELECT s.id
  FROM sample s
 WHERE s.rank = 1

我包括了yw列,以防您想/需要按该列进行筛选。

谢谢,但第二个代码实际上不起作用-显示pref_money tableoops中的所有行。。。试图清理它破坏了加入条件。谢谢。一旦您准备好选择pref_money.id,pref_money.yw from…..时,此操作也有效。。。。。