我想更新表中列的前 10 个值。我有三列;id
,account
和accountrank
. 要获得前 10 个值,我可以使用以下内容:
SELECT * FROM accountrecords
ORDER BY account DESC
LIMIT 10;
我想做的是根据 的大小将 in 的值设置为accountrank
一系列。这可以在 PostgreSQL 中做到吗?1 - 10
account
我想更新表中列的前 10 个值。我有三列;id
,account
和accountrank
. 要获得前 10 个值,我可以使用以下内容:
SELECT * FROM accountrecords
ORDER BY account DESC
LIMIT 10;
我想做的是根据 的大小将 in 的值设置为accountrank
一系列。这可以在 PostgreSQL 中做到吗?1 - 10
account
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
可靠的。请参阅上面的链接。
当然,您可以在子查询中使用您的 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
,那么它们将获得相同的排名。您可以认为这是一个功能... :-)