使用PostgreSQL更新前N个值(Update top N values using Postg

2019-08-02 04:58发布

我想在更新表列的前10个值。 我有三列; idaccountaccountrank 。 为了得到前10个值,我可以使用以下命令:

SELECT  * FROM accountrecords    
ORDER BY account DESC
LIMIT 10;

我想要做的是设置在价值accountrank是一个系列的1 - 10的基础上的大小account 。 这是可能的PostgreSQL的呢?

Answer 1:

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值排在最前面:

  • PostgreSQL的排序日期时间递增,空第一?

如果有可能并发写入访问,上面的查询是受竞争条件 。 考虑:

  • 原子更新。在Postgres的选择
  • Postgres的更新中... LIMIT 1

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

使用CTE,而不是一个普通的子查询(如我在第一个)来执行LIMIT可靠。 见上面的链接。



Answer 2:

当然,你可以在一个子查询使用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 ,那么他们将得到相同的等级。 你可以认为这是一个功能... :-)



文章来源: Update top N values using PostgreSQL