15

我想更新表中列的前 10 个值。我有三列;id,accountaccountrank. 要获得前 10 个值,我可以使用以下内容:

SELECT  * FROM accountrecords    
ORDER BY account DESC
LIMIT 10;

我想做的是根据 的大小将 in 的值设置为accountrank一系列。这可以在 PostgreSQL 中做到吗?1 - 10account

4

2 回答 2

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

加入表表达式通常比相关子查询快。它也更短。

使用窗口函数row_number()可以保证不同的数字。如果您希望具有相同值的行共享相同的数字,请使用rank()(或可能)。dense_rank()account

仅当 中可以有NULL值时account,您才需要附加NULLS LAST降序排序,或者NULL值在顶部排序:

如果可以同时进行写访问,则上述查询会受到竞争条件的影响。考虑:

然而,如果是这样的话,硬编码前十名的整个概念将是一种可疑的方法。

使用 CTE 而不是普通的子查询(就像我一开始那样)来执行LIMIT可靠的。请参阅上面的链接。

于 2012-11-02T00:32:32.507 回答
3

当然,您可以在子查询中使用您的 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,那么它们将获得相同的排名。您可以认为这是一个功能... :-)

于 2012-11-02T00:19:56.937 回答