MySQL 使用 DELETE FROM 删除重复行
MySQL use DELETE FROM to remove duplicates rows
我正在学习 MySQL,今天我尝试解决一个关于 leetcode 的 MySQL 问题:https://leetcode.com/problems/delete-duplicate-emails/solution/
+----+------------------+
| Id | Email |
+----+------------------+
| 1 | john@example.com |
| 2 | bob@example.com |
| 3 | john@example.com |
+----+------------------+
Id is the primary key column for this table.
基本思路是从 table 中删除重复的行,只保留 ID 最小的行。预期结果:
+----+------------------+
| Id | Email |
+----+------------------+
| 1 | john@example.com |
| 2 | bob@example.com |
+----+------------------+
解决方法是
DELETE p1 FROM Person p1,Person p2
WHERE
p1.Email = p2.Email AND p1.Id > p2.Id
我自己尝试了第二个测试用例:
+----+------------------+
| Id | Email |
+----+------------------+
| 1 | john@example.com |
| 2 | bob@example.com |
| 3 | john@example.com |
| 4 | john@example.com |
+----+------------------+
输出为:
+----+------------------+
| Id | Email |
+----+------------------+
| 1 | john@example.com |
| 2 | bob@example.com |
+----+------------------+
我不明白为什么条件 p1.Id > p2.Id 只保留具有最小 id 的行,因为我认为它只排除较小的行,它不适用于
重复次数超过 2 次的情况,对吗?但是正如第二个测试用例所示,它确实有效。
我认为这是因为
的语法
DELETE Table1
FROM Table1
INNER JOIN Table2 ON Table1.ID = Table2.ID
这究竟是如何工作的?有哪位大侠能给我解释一下吗,谢谢!
所以我想我自己找到了原因。这里的 DELETE 与普通的 DELETE 语句不完全一样
DELETE
FROM TABLE
WHERE conditions
而是
DELETE T1, T2
FROM T1
INNER JOIN T2 ON T1.key = T2.key
WHERE condition;
它通常被称为 MySQL DELETE JOIN statement
,这就是它的工作原理。
这取决于你想删除什么
尝试将您的查询更改为
DELETE p2 FROM Person p1,Person p2
WHERE
p1.Email = p2.Email AND p1.Id > p2.Id
你会看到不同的结果
如果您为此尝试 SELECT 语句(同时删除 WHERE p1 > p2)
SELECT p1.*, p2.*, CASE WHEN p1.Id > p2.Id THEN 1 ELSE 0 END
FROM Person p1,Person p2
WHERE p1.Email = p2.Email
您可以检查条件语句的值。 ID 3和4满足条件,则在table.
中删除
enter image description here
我建议您在调试脚本时对 JOIN 的 UPDATE 和 INSERT 操作执行相同的操作以查看数据的外观。
我建议这样表述查询:
delete t
from mytable t
inner join (select email, min(id) as min_id from mytable group by email) t1
on t.email = t1.email and t.id > t1.min_id
这将加入自 table 反对 returns 每个 email
的最小值 id
的聚合查询。为什么我建议这是每行只匹配一次,而不是没有聚合的自连接方法,如果给定的电子邮件有超过 2 个重复项,最终会多次删除同一行。在这方面,上述查询更有效,而且更安全。
首先,这是一种非常糟糕的代码实现方式。但我想一分钱一分货。
其次,简单地 运行 查询作为 select
:
SELECT p1.*, p2.*
FROM Person p1 JOIN
Person p2
ON p1.Email = p2.Email AND p1.Id > p2.Id;
(请注意,我已将逻辑重写为 JOIN
。您应该 始终 使用正确的、明确的、标准, 可读 JOIN
语法,但这两种方法在功能上是等价的。)
在你的第二个例子中,这个查询的结果是:
table1 email table1 id table2 id
john@example.com. 2 1
john@example.com. 3 1
john@example.com. 3 2
值得注意的是 id = 1 永远不会出现在第二列中——这是确定删除哪些 ID 的列。换句话说,除了每封电子邮件的最小 ID 外,其他所有 ID 都会被删除,因为有一个更小的 id
.
这也暗示了为什么这是一个非常糟糕的解决方案。 MySQL 必须处理 id = 3
的两行。也许它试图同时删除两者。也许它只需要处理额外的数据。无论哪种方式,都有额外的工作。数据中包含相同电子邮件的行越多,创建的重复项就越多。
另一种方法,例如:
delete p
from person p join
(select email, min(id) as min_id
from person p2
group by email
) p2
on p.email = p2.email and p.id > p2.min_id;
没有这个问题,在我看来,意图更明确。
我正在学习 MySQL,今天我尝试解决一个关于 leetcode 的 MySQL 问题:https://leetcode.com/problems/delete-duplicate-emails/solution/
+----+------------------+
| Id | Email |
+----+------------------+
| 1 | john@example.com |
| 2 | bob@example.com |
| 3 | john@example.com |
+----+------------------+
Id is the primary key column for this table.
基本思路是从 table 中删除重复的行,只保留 ID 最小的行。预期结果:
+----+------------------+
| Id | Email |
+----+------------------+
| 1 | john@example.com |
| 2 | bob@example.com |
+----+------------------+
解决方法是
DELETE p1 FROM Person p1,Person p2
WHERE
p1.Email = p2.Email AND p1.Id > p2.Id
我自己尝试了第二个测试用例:
+----+------------------+
| Id | Email |
+----+------------------+
| 1 | john@example.com |
| 2 | bob@example.com |
| 3 | john@example.com |
| 4 | john@example.com |
+----+------------------+
输出为:
+----+------------------+
| Id | Email |
+----+------------------+
| 1 | john@example.com |
| 2 | bob@example.com |
+----+------------------+
我不明白为什么条件 p1.Id > p2.Id 只保留具有最小 id 的行,因为我认为它只排除较小的行,它不适用于 重复次数超过 2 次的情况,对吗?但是正如第二个测试用例所示,它确实有效。 我认为这是因为
的语法DELETE Table1
FROM Table1
INNER JOIN Table2 ON Table1.ID = Table2.ID
这究竟是如何工作的?有哪位大侠能给我解释一下吗,谢谢!
所以我想我自己找到了原因。这里的 DELETE 与普通的 DELETE 语句不完全一样
DELETE
FROM TABLE
WHERE conditions
而是
DELETE T1, T2
FROM T1
INNER JOIN T2 ON T1.key = T2.key
WHERE condition;
它通常被称为 MySQL DELETE JOIN statement
,这就是它的工作原理。
这取决于你想删除什么 尝试将您的查询更改为
DELETE p2 FROM Person p1,Person p2
WHERE
p1.Email = p2.Email AND p1.Id > p2.Id
你会看到不同的结果
如果您为此尝试 SELECT 语句(同时删除 WHERE p1 > p2)
SELECT p1.*, p2.*, CASE WHEN p1.Id > p2.Id THEN 1 ELSE 0 END
FROM Person p1,Person p2
WHERE p1.Email = p2.Email
您可以检查条件语句的值。 ID 3和4满足条件,则在table.
中删除enter image description here
我建议您在调试脚本时对 JOIN 的 UPDATE 和 INSERT 操作执行相同的操作以查看数据的外观。
我建议这样表述查询:
delete t
from mytable t
inner join (select email, min(id) as min_id from mytable group by email) t1
on t.email = t1.email and t.id > t1.min_id
这将加入自 table 反对 returns 每个 email
的最小值 id
的聚合查询。为什么我建议这是每行只匹配一次,而不是没有聚合的自连接方法,如果给定的电子邮件有超过 2 个重复项,最终会多次删除同一行。在这方面,上述查询更有效,而且更安全。
首先,这是一种非常糟糕的代码实现方式。但我想一分钱一分货。
其次,简单地 运行 查询作为 select
:
SELECT p1.*, p2.*
FROM Person p1 JOIN
Person p2
ON p1.Email = p2.Email AND p1.Id > p2.Id;
(请注意,我已将逻辑重写为 JOIN
。您应该 始终 使用正确的、明确的、标准, 可读 JOIN
语法,但这两种方法在功能上是等价的。)
在你的第二个例子中,这个查询的结果是:
table1 email table1 id table2 id
john@example.com. 2 1
john@example.com. 3 1
john@example.com. 3 2
值得注意的是 id = 1 永远不会出现在第二列中——这是确定删除哪些 ID 的列。换句话说,除了每封电子邮件的最小 ID 外,其他所有 ID 都会被删除,因为有一个更小的 id
.
这也暗示了为什么这是一个非常糟糕的解决方案。 MySQL 必须处理 id = 3
的两行。也许它试图同时删除两者。也许它只需要处理额外的数据。无论哪种方式,都有额外的工作。数据中包含相同电子邮件的行越多,创建的重复项就越多。
另一种方法,例如:
delete p
from person p join
(select email, min(id) as min_id
from person p2
group by email
) p2
on p.email = p2.email and p.id > p2.min_id;
没有这个问题,在我看来,意图更明确。