2010-12-12 31 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列,在你想/需要的情況下通過要過濾的列。