SQL 查询行迁移到它们的关系的不同出现
SQL query for rows migration to distinct occurences of their relations
我有以下包含示例数据的数据结构:
群组Table
id (PK)
name
foreign_id
A
DUPLICATED_NAME
X
B
DUPLICATED_NAME
X
C
string
Y
D
string
Z
项目Table(与群组相关)
id (PK)
group_id
uuid value1
A
uuid value2
B
uuid value3
C
uuid value4
D
我的目标是摆脱 Groups 中的 id 列并创建 name 和foreign_id 列新复合主键。
为此,我需要将现有的 项 迁移到不同的 组 。
例如,我发布的意思是,我需要删除 id = B 组,因为 DUPLICATED_NAME 与 group A,然后将所有 items 重新分配给 group_id = B 到 A,因为 B 不再存在,依此类推,对于所有行.
我正在使用 PostgresSQL 和 Liquibase。
UPDATE items i
SET group_id = s.first_value -- 3
FROM (
SELECT
i.*,
g.first_value
FROM items i
JOIN (
SELECT
*,
-- 1
first_value(id) OVER (PARTITION BY name, foreign_key ORDER BY id)
FROM groups
) g ON g.id = i.group_id -- 2
) s
WHERE i.id = s.id;
- 使用
first_value()
window function 查找重复组的第一个 id 值,该值作为唯一值添加到组的所有记录(=分区)
- 由老
group_id
加入group
table上items
table
- 使用
first_value
更新 items
table
如果要在同一个查询中为 groups
table 执行 DELETE
语句,可以使用 CTEs (WITH
clauses):
WITH new_group_id AS (
SELECT -- 1
i.*,
g.id as g_id,
g.first_value
FROM items i
JOIN (
SELECT
*,
first_value(id) OVER (PARTITION BY name, foreign_key ORDER BY id)
FROM groups
) g ON g.id = i.group_id
), update_items AS (
UPDATE items i -- 2
SET group_id = s.first_value
FROM (SELECT * FROM new_group_id) s
WHERE s.id = i.id
)
DELETE FROM groups -- 3
WHERE id IN (
SELECT g_id
FROM new_group_id
WHERE g_id <> first_value
);
- 首先像上面那样计算新的group_id。将结果存储在 CTE 中,因为我们稍后会重复使用它两次。
- 像上面那样做
UPDATE
语句。唯一不同的是,我们没有使用子查询,而是使用之前计算的 CTE 结果
- 更新后我们可以再次使用查询来查找应该删除的记录(每条
first_value
与实际组的id
不相同的记录)。执行DELETE
语句。
我有以下包含示例数据的数据结构:
群组Table
id (PK) | name | foreign_id |
---|---|---|
A | DUPLICATED_NAME | X |
B | DUPLICATED_NAME | X |
C | string | Y |
D | string | Z |
项目Table(与群组相关)
id (PK) | group_id |
---|---|
uuid value1 | A |
uuid value2 | B |
uuid value3 | C |
uuid value4 | D |
我的目标是摆脱 Groups 中的 id 列并创建 name 和foreign_id 列新复合主键。
为此,我需要将现有的 项 迁移到不同的 组 。 例如,我发布的意思是,我需要删除 id = B 组,因为 DUPLICATED_NAME 与 group A,然后将所有 items 重新分配给 group_id = B 到 A,因为 B 不再存在,依此类推,对于所有行.
我正在使用 PostgresSQL 和 Liquibase。
UPDATE items i
SET group_id = s.first_value -- 3
FROM (
SELECT
i.*,
g.first_value
FROM items i
JOIN (
SELECT
*,
-- 1
first_value(id) OVER (PARTITION BY name, foreign_key ORDER BY id)
FROM groups
) g ON g.id = i.group_id -- 2
) s
WHERE i.id = s.id;
- 使用
first_value()
window function 查找重复组的第一个 id 值,该值作为唯一值添加到组的所有记录(=分区) - 由老
group_id
加入 - 使用
first_value
更新
group
table上items
table
items
table
如果要在同一个查询中为 groups
table 执行 DELETE
语句,可以使用 CTEs (WITH
clauses):
WITH new_group_id AS (
SELECT -- 1
i.*,
g.id as g_id,
g.first_value
FROM items i
JOIN (
SELECT
*,
first_value(id) OVER (PARTITION BY name, foreign_key ORDER BY id)
FROM groups
) g ON g.id = i.group_id
), update_items AS (
UPDATE items i -- 2
SET group_id = s.first_value
FROM (SELECT * FROM new_group_id) s
WHERE s.id = i.id
)
DELETE FROM groups -- 3
WHERE id IN (
SELECT g_id
FROM new_group_id
WHERE g_id <> first_value
);
- 首先像上面那样计算新的group_id。将结果存储在 CTE 中,因为我们稍后会重复使用它两次。
- 像上面那样做
UPDATE
语句。唯一不同的是,我们没有使用子查询,而是使用之前计算的 CTE 结果 - 更新后我们可以再次使用查询来查找应该删除的记录(每条
first_value
与实际组的id
不相同的记录)。执行DELETE
语句。