使用唯一对值的整数序列更新 postgres 列

Updating postgres column with sequence of integers for unique pairs values

我有 postgres table user_team,它有 user_pkteamexerciseassigned_at 列,我想自动- 使用递增整数序列填充 order 列,但仅适用于唯一的 user_pkteam 对并按 assigned_at 排序: 所以我的专栏是:

|  user_pk    |  team          |  exercise_pk  | assigned_at  |  
|-------------------------------------------------------------|
| 111         | blue           |  "exercise"   | 2022-03-01   |
| 111         | blue           |  "exercise"   | 2022-03-02   |
| 222         | blue           |  "exercise"   | 2022-03-01   |
| 222         | blue           |  "exercise"   | 2022-03-02   |
| 222         | blue           |  "exercise"   | 2022-03-03   |
| 111         | green          |  "exercise"   | 2022-03-01   |
| 111         | green          |  "exercise"   | 2022-03-02   |
| 111         | green          |  "exercise"   | 2022-03-03   |
| 333         | green          |  "exercise"   | 2022-03-01   |
| 333         | green          |  "exercise"   | 2022-03-02   |

我想要

|  user_pk    |  team          |  exercise_pk  | assigned_at  | order|
|--------------------------------------------------------------------|
| 111         | blue           |  "exercise"   | 2022-03-01   |1     |
| 111         | blue           |  "exercise"   | 2022-03-02   |2     |
| 222         | blue           |  "exercise"   | 2022-03-01   |1     |
| 222         | blue           |  "exercise"   | 2022-03-02   |2     |
| 222         | blue           |  "exercise"   | 2022-03-03   |3     |
| 111         | green          |  "exercise"   | 2022-03-01   |1     |
| 111         | green          |  "exercise"   | 2022-03-02   |2     |
| 111         | green          |  "exercise"   | 2022-03-03   |3     |
| 333         | green          |  "exercise"   | 2022-03-01   |1     |
| 333         | green          |  "exercise"   | 2022-03-02   |2     |

有没有办法在一个查询中做到这一点? 我尝试使用 DISTINCT user_pk, team 并回答来自: :

    update bar b
   set id = b2.new_id
   from (select b.*, row_number() over (order by id) as new_id
         from bar
        ) b2;
   where b.pk = b2.pk;

但还是想不通

很高兴您找到了类似的问题。但是你实际尝试解决你的问题是什么,你不能只是从那里复制一个答案并期望它甚至与你的需要相关。这只是提供了一种可能适用的格式。

你需要的是识别一个唯一的列或一组唯一的列来识别特定的行,从那里使用 row_number 为每个唯一的 value/set 分配所需的值,最后匹配 generated/extracted 标识符以获得所需的结果列。在下面,CTE 使用列 user_pk, team, assigned_at 来标识特定行和目标新列值。然后主要部分匹配这些列进行更新。 (参见 demo

with ord_num( user_pk, team, assigned_at, order_seq)  as 
     ( select user_pk, team, assigned_at
            , row_number() over (partition by  user_pk, team 
                                     order by  user_pk, team, assigned_at
                                )
         from user_team 
      )
update user_team ut
   set order_seq = 
       (select order_seq 
          from ord_num os 
         where (ut.user_pk, ut.team, ut.assigned_at) = 
               (os.user_pk, os.team, os.assigned_at)
       ) ;

注意: 将用户 order 作为列名是非常糟糕的做法。它既是 Postgres 又是 SQL 标准 reserved word。虽然你可以侥幸逃脱,但最好的结果只是混乱,最坏的情况是处理失败,因为做了不正确的事情而不提供任何消息。导致数据完全损坏。也适用于任何保留字。