2010-12-12 24 views
2

我有以下表持有虚拟货币用于每周的比赛:PostgreSQL的:如何找到的,最大货币ID在每周表

# 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语句,使被选中真的只有赢家IDS?

当我尝试以下方法,我得到一个错误:

# 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 

谢谢! 亚历

UPDATE:在PostgreSQL 8.4.5/CentOS的并且可以有关系:-)

回答

3

哪个版本的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()

+0

+1:6秒打我! – 2010-12-12 18:40:11

+0

谢谢,但第二个代码并没有真正的工作 - 显示所有行pref_money表 – 2010-12-12 19:52:47

+0

哎呀......试图neaten它打破了连接条件。 – araqnid 2010-12-12 20:00:29

2

假设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列,在你想/需要的情况下通过要过滤的列。