196. 删除重复的电子邮箱
题目描述
表: Person
+-------------+---------+ | Column Name | Type | +-------------+---------+ | id | int | | email | varchar | +-------------+---------+ id 是该表的主键列(具有唯一值的列)。 该表的每一行包含一封电子邮件。电子邮件将不包含大写字母。
编写解决方案 删除 所有重复的电子邮件,只保留一个具有最小 id 的唯一电子邮件。
(对于 SQL 用户,请注意你应该编写一个 DELETE 语句而不是 SELECT 语句。)
(对于 Pandas 用户,请注意你应该直接修改 Person 表。)
运行脚本后,显示的答案是 Person 表。驱动程序将首先编译并运行您的代码片段,然后再显示 Person 表。Person 表的最终顺序 无关紧要 。
返回结果格式如下示例所示。
示例 1:
输入: Person 表: +----+------------------+ | id | email | +----+------------------+ | 1 | john@example.com | | 2 | bob@example.com | | 3 | john@example.com | +----+------------------+ 输出: +----+------------------+ | id | email | +----+------------------+ | 1 | john@example.com | | 2 | bob@example.com | +----+------------------+ 解释: john@example.com重复两次。我们保留最小的Id = 1。
解法
方法一
思考
同一邮箱只留 \(\textit{id}\) 最小的那一行。按邮箱分组取 \(\textit{MIN}(\textit{id})\),删除不在这个集合里的行。子查询再包一层是为了让 MySQL 允许对正在删除的表做聚合。
1 2 3 4 5 6 7 8 9 | |
1 2 3 | |
方法二
思考
方法一用聚合子查询。窗口 \(\textit{ROW\_NUMBER}\) 按邮箱分区、按 \(\textit{id}\) 排序,编号大于 \(1\) 的即重复行,删除它们,语义更直观。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
方法三
思考
不必先算出保留集合。自连接同一邮箱且 \(p1.\textit{id}<p2.\textit{id}\),直接删掉 \(\textit{id}\) 较大的那一侧,一条 \(\textit{DELETE}\,\textit{JOIN}\) 完成。
1 2 3 4 5 6 | |