如何使用重复 ID 更新引用 table?
How to update reference table with duplicate id?
我正在使用 postgresql。
要删除 table 中的重复项,我使用此查询:
DELETE FROM dups a USING (
SELECT MIN(ctid) as ctid, key
FROM dups
GROUP BY key HAVING COUNT(*) > 1
) b
WHERE a.key = b.key
AND a.ctid <> b.ctid
参考:
但是,还有一个 table 说 ref_table
,其中也引用了 dups.id
。在删除重复项之前,我需要更新另一个 table。
用重复的 ID 更新引用 table 的查询是什么,这样就不会丢失数据?
例如:
Table 1、说dups
id key
1 Luna
2 Hermione
3 Luna
Table 2、说ref_table
id dups_id data
1 2 Auror
2 1 Researcher
现在删除重复项的查询将删除 dups table 中 ID 为 1 的记录,因为它是重复项。
但是 ref_table
中引用了该记录,因此我需要使用将要保留的记录更新它。
即)Table1 应该变成:
id key
2 Hermione
3 Luna
和Table 2 应该变成:
id dups_id data
1 2 Auror
2 3 Researcher
您可以使用 CTE:
with d as (
DELETE FROM dups a USING
(SELECT MIN(ctid) as ctid, key
FROM dups
GROUP BY key HAVING COUNT(*) > 1
) b
WHERE a.key = b.key AND a.ctid <> b.ctid
RETURNING *
)
update othertable
set . . .
from d
where . . .;
使用 CTE 来识别 dups 中维护的行,然后更新 ref 行,使 FK 仅指向它们,最后删除不再需要的行。
with keeper as -- identify dups rows to be kept
( select id, key
, max(id) over(partition by key) mid
from dups)
, u as -- update ref so dup_id references only those being kept
( update ref r
set dup_id = (select k.mid
from keeper k
join dups d
on (k.id=d.id)
where r.dup_id != k.mid
and r.dup_id = k.id
)
)
delete -- final target remove dups rows no lnger needed
from dups d
where d.id not in (select mid from keeper);
我正在使用 postgresql。 要删除 table 中的重复项,我使用此查询:
DELETE FROM dups a USING (
SELECT MIN(ctid) as ctid, key
FROM dups
GROUP BY key HAVING COUNT(*) > 1
) b
WHERE a.key = b.key
AND a.ctid <> b.ctid
参考:
但是,还有一个 table 说 ref_table
,其中也引用了 dups.id
。在删除重复项之前,我需要更新另一个 table。
用重复的 ID 更新引用 table 的查询是什么,这样就不会丢失数据?
例如:
Table 1、说dups
id key
1 Luna
2 Hermione
3 Luna
Table 2、说ref_table
id dups_id data
1 2 Auror
2 1 Researcher
现在删除重复项的查询将删除 dups table 中 ID 为 1 的记录,因为它是重复项。
但是 ref_table
中引用了该记录,因此我需要使用将要保留的记录更新它。
即)Table1 应该变成:
id key
2 Hermione
3 Luna
和Table 2 应该变成:
id dups_id data
1 2 Auror
2 3 Researcher
您可以使用 CTE:
with d as (
DELETE FROM dups a USING
(SELECT MIN(ctid) as ctid, key
FROM dups
GROUP BY key HAVING COUNT(*) > 1
) b
WHERE a.key = b.key AND a.ctid <> b.ctid
RETURNING *
)
update othertable
set . . .
from d
where . . .;
使用 CTE 来识别 dups 中维护的行,然后更新 ref 行,使 FK 仅指向它们,最后删除不再需要的行。
with keeper as -- identify dups rows to be kept
( select id, key
, max(id) over(partition by key) mid
from dups)
, u as -- update ref so dup_id references only those being kept
( update ref r
set dup_id = (select k.mid
from keeper k
join dups d
on (k.id=d.id)
where r.dup_id != k.mid
and r.dup_id = k.id
)
)
delete -- final target remove dups rows no lnger needed
from dups d
where d.id not in (select mid from keeper);