PostgreSQL:设置一个列,其中的行序号通过另一个字段排序

PostgreSQL:设置一个列,其中的行序号通过另一个字段排序,postgresql,Postgresql,我有一个表segnature,它用一个varchar字段deno和一个数值字段ord描述一个项。外键fk_集合告诉行是哪个集合的一部分 我想更新字段ord,以便它包含每个集合中该行的序号,按字段deno排序 例如,如果我有 [deno] ord [fk_collection] abc 10 aab 10 bcd 10 zxc 20 vbn 20 upda

我有一个表segnature,它用一个varchar字段deno和一个数值字段ord描述一个项。外键fk_集合告诉行是哪个集合的一部分

我想更新字段ord,以便它包含每个集合中该行的序号,按字段deno排序

例如,如果我有

[deno]     ord   [fk_collection]
abc              10
aab              10
bcd              10
zxc              20
vbn              20
update segnature s1 set ord = (select count(*) 
    from segnature s2 
    where s1.fk_collection=s2.fk_collection and s2.deno<s1.deno
)
然后我想要一个这样的结果

[deno]     ord   [fk_collection]
abc          1   10
aab          0   10
bcd          2   10
zxc          1   20
vbn          0   20
我试过用类似的东西

[deno]     ord   [fk_collection]
abc              10
aab              10
bcd              10
zxc              20
vbn              20
update segnature s1 set ord = (select count(*) 
    from segnature s2 
    where s1.fk_collection=s2.fk_collection and s2.deno<s1.deno
)
但查询速度真的很慢:每30000个项目中有150个集合在10分钟左右更新

有没有加快这一进程的建议


谢谢大家!

您可以使用窗口函数生成序号:

with numbered as (
   select deno, fk_collection, 
          row_number() over (partition by fk_collection order by deno) as rn, 
          ctid as id
   from segnature
) 
update segnature
  set ord = n.rn
from numbered n
where n.id = segnature.ctid;
这将使用内部列唯一标识每一行。ctid比较非常慢,因此如果该表中有真正的主键或唯一键,请使用该列

或者,如果没有:


SQLFiddle示例:

Perfect:我在每一行上都有一个pk_id,所以我调整了您的查询以使用pk,现在它就像一个符咒:大约1秒对10分钟是一个巨大的改进!我不知道窗口的功能,我必须学习它们是如何工作的。非常感谢你!