使用唯一对值的整数序列更新 postgres 列
Updating postgres column with sequence of integers for unique pairs values
我有 postgres table user_team
,它有 user_pk
、team
、exercise
、assigned_at
列,我想自动- 使用递增整数序列填充 order
列,但仅适用于唯一的 user_pk
和 team
对并按 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。虽然你可以侥幸逃脱,但最好的结果只是混乱,最坏的情况是处理失败,因为做了不正确的事情而不提供任何消息。导致数据完全损坏。也适用于任何保留字。
我有 postgres table user_team
,它有 user_pk
、team
、exercise
、assigned_at
列,我想自动- 使用递增整数序列填充 order
列,但仅适用于唯一的 user_pk
和 team
对并按 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。虽然你可以侥幸逃脱,但最好的结果只是混乱,最坏的情况是处理失败,因为做了不正确的事情而不提供任何消息。导致数据完全损坏。也适用于任何保留字。