使用PostgreSQL更新前N个值

时间:2012-11-02 00:11:19

标签: sql postgresql sql-update sql-order-by sql-limit

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

SELECT  * FROM accountrecords    
ORDER BY account DESC
LIMIT 10;

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

2 个答案:

答案 0 :(得分:26)

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;

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

保证window function row_number()个不同的数字。如果您希望rank()的值相等的行共享相同的数字,请使用dense_rank()(或可能account)。

仅当NULL中有account个值时,您才需要附加NULLS LAST以降序排序,或者NULL值排在最前面:

如果可以进行并发写访问,则上述查询受竞争条件的约束。考虑:

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

使用CTE而不是普通子查询(就像我最初那样)来可靠地强制执行LIMIT。见上面的链接。

答案 1 :(得分: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具有相同的值,那么它们将获得相同的等级。你可以考虑一个特征......: - )