2012-11-02 59 views
9

我想更新表中列的前10個值。我有三列; idaccountaccountrank。爲了得到前10個值,我可以使用以下命令:使用PostgreSQL更新前N個值

SELECT * FROM accountrecords  
ORDER BY account DESC 
LIMIT 10; 

我想這樣做是accountrank設定值是一系列1 - 10的基礎上,account幅度。這可能在PostgreSQL中做到嗎?

+2

如果您的poatgres版本是8.4或以上,您可以使用窗口函數+ rank()或row_number()。 – wildplasser

回答

22
UPDATE accountrecords a 
SET accountrank = sub.rn 
FROM (
    SELECT id, row_number() OVER (ORDER BY account DESC NULLS LAST) AS rn 
    FROM accountrecords  
    ORDER BY account DESC NULLS LAST 
    LIMIT 10 
    ) sub 
WHERE sub.id = a.id; 

加入表格通常比關聯的子查詢更快。它也更短。

window function row_number()不同的數字是有保證的。如果您希望account具有相同值的行共享相同的編號,請使用rank()(或可能爲dense_rank())。

只有當有可以在accountNULL值,則需要追加NULLS LAST爲降序排序,或者NULL值排在最前面:

如果有可能併發寫訪問,上述查詢受競爭條件。試想一下:

但是,如果是這樣的話,整個概念硬編碼的前十名將開始與一個可疑的做法。

1

當然,你可以在子查詢中使用你的select語句。生成排名並不重要,但至少有一種方法可以實現。我沒有測試過這一點,但我的頭頂部:

update accountrecords 
set accountrank = 
    (select count(*) + 1 from accountrecords r where r.account > account) 
where id in (select id from accountrecords order by account desc limit 10); 

這有怪癖,如果兩個記錄具有相同的價值account,那麼他們將得到相同的等級。您可以考慮一個功能... :-)