2012-11-02 17 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,那么他们将得到相同的等级。您可以考虑一个功能... :-)