有效地更新PostgreSQL中2条记录中的值的方法

时间:2018-10-15 19:47:38

标签: postgresql performance

我有一个包含4列的表

id | category | score | enabled
1  |  news    |  95   |    t

id-序列

category-varchar

score-浮动

enabled-布尔

如果还有另一条得分更高的记录,我想将enabled更新为False

例如,如果我有:

id | category | score | enabled
1  |  news    |  95   |    t

然后,在执行一些操作后,将插入具有相同类别的新记录:

id | category | score | enabled
1  |  news    |  95   |    t
2  |  news    |  100  |    f

由于id=2的得分较高,我想将enabled的{​​{1}}更改为id=2,并将True的{​​{1}}更改为enabled

我想知道是否可以将这些操作合并为1个查询。现在,我进行2个id=1查询以获取2条记录,然后在本地比较分数,然后更改False值(如果需要)。

很简单,

SELECT

它可以工作,但是效率很低。有什么方法可以改善这些查询?

1 个答案:

答案 0 :(得分:1)

您可以执行一次更新:

update the_table 
  set enabled = (score = t.max_score)
from (
  select id, category, max(score) over (partition by category) as max_score
  from the_table
  where category = 'news'
) t
where t.id = the_table.id
  and t.category = the_table.category;

这将在单个语句中为具有相同类别的所有行设置enabled标志。

在线示例:https://rextester.com/DXR80618

如果您碰巧有一个行的同一类别的最高分得分相同,则以上语句将所有enabled更改为true

例如

id | category | score
---+----------+------
 1 | news     |    95
 2 | news     |   100
 3 | news     |   100

如果您不想要那样,例如始终选择id最低的那个作为已启用的行,您可以使用以下命令:

update the_table 
  set enabled = (rn = 1)
from (
   select id, category, 
          row_number() over (partition by category order by score desc, id) as rn
   from the_table
   where category = 'news'
) t
where t.id = the_table.id
  and t.category = the_table.category;

在线示例:https://rextester.com/JPA61125