PostgreSQL:调整子级上的外键以删除父级中的重复

PostgreSQL:调整子级上的外键以删除父级中的重复,postgresql,Postgresql,我接管了一个项目,该项目在PostgreSQL中有一些需要调整的现有数据。具体来说,在团队属于联盟的系统中,我需要从联盟表中删除重复的名称。为此,我需要调整teams表中的外键,以便它们不再引用将被删除的联赛。请注意,我删除哪些联赛和保留哪些联赛并不重要,只要我为每个不同的联赛名称保留一个联赛名称 用一个例子来解释更容易。下面我们可以看到,红松鼠和绿猴子都属于西部联盟,尽管目前有两排名称为西部联盟。我需要删除leagues表中的行,以便联赛名称是唯一的,但首先我需要更改teams表中的leagu

我接管了一个项目,该项目在PostgreSQL中有一些需要调整的现有数据。具体来说,在团队属于联盟的系统中,我需要从联盟表中删除重复的名称。为此,我需要调整teams表中的外键,以便它们不再引用将被删除的联赛。请注意,我删除哪些联赛和保留哪些联赛并不重要,只要我为每个不同的联赛名称保留一个联赛名称

用一个例子来解释更容易。下面我们可以看到,红松鼠和绿猴子都属于西部联盟,尽管目前有两排名称为西部联盟。我需要删除leagues表中的行,以便联赛名称是唯一的,但首先我需要更改teams表中的league_ID,以便它们引用不会被删除的联赛行

  leagues
  id  | name
  1   | "Western League"
  2   | "Western League"
  3   | "Eastern League"

  teams
  id  | league_id | name
  1   | 1         | "Red Squirrels"
  2   | 2         | "Green Monkeys"
  3   | 3         | "Blue Ducks"
在上面的简单示例中,目标是将绿猴子的league_id更改为1,这样红松鼠和绿猴子都引用相同的联盟。在此之后,没有球队参考第二个西部联赛,它可以被删除。但是,我们有太多的数据,无法逐行进行更改


非常感谢你在这方面的帮助。谢谢

此查询显示哪个联赛应替换为另一个联赛:

select id, min(id) over (partition by name) as correct_id
from leagues

 id | correct_id 
----+------------
  3 |          3    -- ok
  1 |          1    -- ok
  2 |          1    -- needs replacing
(3 rows)
如果我们加入团队,我们可以选择需要纠正的团队:

select t.id as team_id, correct_id
from (
    select id, min(id) over (partition by name) as correct_id
    from leagues
    ) l
join teams t on t.league_id = l.id
where t.league_id <> correct_id

 team_id | correct_id 
---------+------------
       2 |          1
(1 row)
使用最后一个查询更新团队:

update teams
set league_id = correct_id
from (
    select t.id as team_id, correct_id
    from (
        select id, min(id) over (partition by name) as correct_id
        from leagues
        ) l
    join teams t on t.league_id = l.id
    where t.league_id <> correct_id
    ) c
where id = team_id
returning team_id, name, correct_id

 team_id |      name       | correct_id 
---------+-----------------+------------
       2 | "Green Monkeys" |          1
(1 row) 

嗨,克林,我真的很感谢你花时间提供如此详细和准确的答案。这非常有效,也教会了我很多。再次感谢您,祝您度过愉快的一天!