Postgres UPDATE使用排名窗口功能

时间:2016-10-28 00:38:36

标签: sql postgresql

我有一个名为medias的表格,我最近刚刚添加了一个名为sort_order Int的新列。

行值不是整个表的唯一值,而是它们各自的owner_user_id字段的唯一值。无论如何,我甚至不关心他们的独特性。

所有这一切的要点是允许用户设置他们上传的照片的排序顺序(最多10个,他们可以拖动和重新排序等)。当用户“删除”照片时,我不会删除记录,只需在该行上设置visible字段为false

Aaaanyway,我正在推出一项添加sort_order的迁移(他们过去无法订购照片,只会根据order by created_at asc进行排序)。

自添加新字段以来,我已将新sort_order的默认值设置为10(因此它向后兼容尚未更新应用程序的人员。)

我能够提出这个问题:

select
  owner_user_id, 
  sort_order, rank() over (PARTITION BY owner_user_id ORDER BY sort_order asc, created_at asc) as new_sort_order 
from medias 
where visible=true 
order by sort_order asc, created_at asc;

这会吐出如下所示的内容:

 owner_user_id | sort_order | new_sort_order
---------------+------------+---------------
            76 |         10 |      1
            76 |         10 |      2
            76 |         10 |      3
            76 |         10 |      4
            76 |         10 |      5
             9 |         10 |      1
             9 |         10 |      2
             9 |         10 |      3
             9 |         10 |      4
             9 |         10 |      5
            79 |         10 |      1
            79 |         10 |      2
            87 |         10 |      1
            87 |         10 |      2
            87 |         10 |      3
            85 |         10 |      1
            90 |         10 |      1
            90 |         10 |      2
            90 |         10 |      3

此时我真正想做的是将sort_order设置为rank()。有关如何做到这一点的任何想法?

2 个答案:

答案 0 :(得分:4)

由于您没有唯一密钥,请使用ctid

update medias m
    set sort_order = new_sort_order
    from (
        select 
            ctid,
            owner_user_id, 
            sort_order, 
            row_number() over w as new_sort_order 
        from medias 
        where visible
        window w as (partition by owner_user_id order by sort_order asc, created_at asc)
    ) s
    where m.ctid = s.ctid;

注意,row_number()可能比rank()更好,因为第一个从不提供重复。

答案 1 :(得分:3)

您可以使用data,但需要唯一ID。我假设你有一个:

join

基本上,您在子查询中进行计算,然后将结果加回到表中以进行更新。