Update top N values using PostgreSQL

你说的曾经没有我的故事 提交于 2019-12-21 07:19:15

问题


I want to update the top 10 values of a column in table. I have three columns; id, account and accountrank. To get the top 10 values I can use the following:

SELECT  * FROM accountrecords    
ORDER BY account DESC
LIMIT 10;

What I would like to do is to set the value in accountrank to be a series of 1 - 10, based on the magnitude of account. Is this possible to do in PostgreSQL?


回答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;

Joining in a table expression is typically faster than correlated subqueries. It is also shorter.

With the window function row_number() distinct numbers are guaranteed. Use rank() (or possibly dense_rank()) if you want rows with equal values for account to share the same number.

Only if there can be NULL values in account, you need to append NULLS LAST for descending sort order, or NULL values sort on top:

  • PostgreSQL sort by datetime asc, null first?

If there can be concurrent write access, the above query is subject to a race condition. Consider:

  • Atomic UPDATE .. SELECT in Postgres
  • Postgres UPDATE … LIMIT 1

However, if that was the case, the whole concept of hard-coding the top ten would be a dubious approach to begin with.

Use a CTE instead of a plain subquery (like I had at first) to enforce the LIMIT reliably. See links above.




回答2:


Sure, you can use your select statement in a subquery. Generating the rank-order isn't trivial, but here's at least one way to do it. I haven't tested this, but off the top of my head:

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);

This has the quirk that if two records have the same value for account, then they will get the same rank. You could consider that a feature... :-)



来源:https://stackoverflow.com/questions/13187419/update-top-n-values-using-postgresql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!