我想更新表格中列的前10个值。我有三列; id
,account
和accountrank
。要获得前10个值,我可以使用以下内容:
SELECT * FROM accountrecords
ORDER BY account DESC
LIMIT 10;
我想要做的是根据accountrank
的幅度将1 - 10
中的值设置为一系列account
。这可以在PostgreSQL中做到吗?
答案 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
具有相同的值,那么它们将获得相同的等级。你可以考虑一个特征......: - )