大多数重复记录属于这两类:重复含义和非唯一键。“如何在 MySQL 中发现和删除具有重复含义的值”文章处理了重复含义的记录。而后续文章 讨论了如何识别非唯一键。这是在同一个表中的两条记录具有相同的键,但可能有或可能没有不同的值和含义。今天的文章将介绍如何删除具有重复数据但具有不同键的行。
按类型识别重复项
在“如何识别具有非唯一键的重复项”文章中显示的最后一个查询以易于查看的格式列出了所有重复项:
Repetitions | row_data | |
---------------------------------------------------------------- | ||
2 | 22 (DAVIS, JENNIFER) | 22 (DAVIS, JENNIFER) | |
2 | 23 (LOLLOBRIGIDA, JOHNNY) | 23 (GABLE, CHRISTIAN) | |
2 | 41 (WAHLBERG, NICK) | 12 (WAHLBERG, NICK) |
确定了所有重复的键和值后,我们就可以决定如何以最佳方式处理冗余数据。
JENNIFER DAVIS 出现在两条记录中,具有相同的键 22,使这些行完全重复。NICK WALBERG 的名字段是重复的,但 ID 不是。还有另一个重复的键 #23,是两条不相关的演员的记录:“JOHNNY LOLLOBRIGIDA”和“CHRISTIAN GABLE”。关于 22 和 23 的重复键,第一个是真正的重复,而第二个只需要为其中一条记录生成新键就可解决。
使用 DELETE JOIN 删除行
在“如何在 MySQL 中发现和删除具有重复含义的值”文章中,我们通过对执行搜索和替换值来从 SELEC T结果集中删除重复项。在这里,我们将使用 DELETE JOIN 语句永久删除其中一个重复的行。
由于我们正在比较同一个表中的字段,因此我们必须将表连接到自身。我们可以在 WHERE子句中比较 id 来选择保留较小或较大的 id 号。以下语句保留最大的 id:
DELETE a FROM wp.amalgamated_actors a INNER JOIN wp.amalgamated_actors a2 WHERE a.id < a2.id AND a.first_name = a2.first_name AND a.last_name = a2.last_name; 1 row(s) affected 0.093 sec
在这种情况下,受影响(已删除)的行是 id 为 12 的 NICK WAHLBERG。快速的 SELECT 语句可确认结果:
id | first_name | last_name | ------------------------------------- | |
10 | PENELOPE | GUINESS | ||
12 | NICK | WAHLBERG | ||
14 | ED | CHASE | ||
22 | JENNIFER | DAVIS | ||
23 | JOHNNY | LOLLOBRIGIDA | ||
27 | BETTE | NICHOLSON | ||
34 | GRACE | MOSTEL | ||
39 | JOE | SWANK | ||
23 | CHRISTIAN | GABLE | ||
22 | JENNIFER | DAVIS |
如果你想保留最小的 id,你只需将 a.id < a2.id 表达式更改为 a.id > a2.id。
id | first_name | last_name | ------------------------------------- | |
10 | PENELOPE | GUINESS | ||
14 | ED | CHASE | ||
22 | JENNIFER | DAVIS | ||
23 | JOHNNY | LOLLOBRIGIDA | ||
27 | BETTE | NICHOLSON | ||
34 | GRACE | MOSTEL | ||
41 | NICK | WAHLBERG | ||
39 | JOE | SWANK | ||
23 | CHRISTIAN | GABLE | ||
22 | JENNIFER | DAVIS |
删除具有非唯一键的行
对于 id 为 22 的 JENNIFER DAVIS 出现两次的情况,我们需要采用不同的方法。因为使用 a.id = a2.id 运行上述语句将针对表中的每一行!原因是我们实质上每一行与自身匹配!在下一篇文章中,我们将学习如何删除像这样具有非唯一键的行。