Mysql

mysql - 如何刪除父表中的重複行並保留最低ID的一行,並用此ID替換子表中的外鍵?

  • April 18, 2020

我有三個表的情況:

hgn_modern_sources
+----+--------------+
| id |    source    |
+----+--------------+
| 17 | Something... |
+----+--------------+

junc_modern_source_has_reference
+----+------------------+------------------------+
| id | modern_source_id | location_within_source |
+----+------------------+------------------------+
| 52 |               17 | 1, 1                   |
| 89 |               17 | 1, 1                   |
| 99 |               17 | 1, 1                   |
+----+------------------+------------------------+

hgn_picture_has_reference
+----+---------------------+-------------------+
| id | modern_reference_id | picture_link      |
+----+---------------------+--------------------+
| 45 | 89                  | /images/image1.png |
| 75 | 99                  | /images/image2.png |
+----+---------------------+--------------------+

我的問題是如何從junc_modern_source_has_reference(id = 89 和 id = 99)中刪除重複項,留下 ID 最低的一行(id = 52),並將hgn_picture_has_reference表(column modern_reference_id)中的外鍵替換為左(id = 52)?

該解決方案只能基於 MySQL,或 PHP + MySQL(我更喜歡)。

定義和範例數據,或者提供小提琴或定義和範例數據,如下所示,以獲得對您的問題的更多吸引力:

create table junc_modern_source_has_reference
( id int not null primary key
, modern_source_id int not null
);

insert into junc_modern_source_has_reference
values (52,17),(89,17),(99,17);

create table hgn_picture_has_reference
( id int not null primary key
, modern_reference_id int not null
);

insert into hgn_picture_has_reference
values (45,89),(75,99);

第一步是將所有行更新為最低 id:

update  hgn_picture_has_reference x
  set modern_reference_id = (select min(y.id) 
                             from junc_modern_source_has_reference y
                             join junc_modern_source_has_reference z
                                 on y.modern_source_id = z.modern_source_id
                             where x.modern_reference_id = z.id )
where exists (
   select min(y.id) 
   from junc_modern_source_has_reference y
   join junc_modern_source_has_reference z
       on y.modern_source_id = z.modern_source_id
   where x.modern_reference_id = z.id 
);

現在我們可以刪除除最低 id 之外的所有內容,這是非標準 SQL,但 MySQL 過去在引用正在修改的表時會遇到問題:

delete x.*
from junc_modern_source_has_reference x
join junc_modern_source_has_reference y
   on x.modern_source_id = y.modern_source_id
  and y.id < x.id
;

標準版本將類似於:

delete x.*
from junc_modern_source_has_reference x
where exists (
   select 1 from junc_modern_source_has_reference y
   where  x.modern_source_id = y.modern_source_id
     and y.id < x.id
);

即,如果同一modern_source_id 有另一行具有較低ID 的行,則刪除行

引用自:https://dba.stackexchange.com/questions/265088