原題題目
表:?
Person
+-------------+---------+ | Column Name | Type | +-------------+---------+ | id | int | | email | varchar | +-------------+---------+ id 是該表的主鍵列(具有唯一值的列)。 該表的每一行包含一封電子郵件。電子郵件將不包含大寫字母。編寫解決方案?刪除?所有重復的電子郵件,只保留一個具有最小?
id
?的唯一電子郵件。(對于 SQL 用戶,請注意你應該編寫一個?
DELETE
?語句而不是?SELECT
?語句。)運行腳本后,顯示的答案是?
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。
方法一 分組
先對郵箱進行分組,然后查找郵箱最小id,形成一個子查詢。
遍歷表格,如果id不在子查詢結果里,則刪除。
注意:
1、這段代碼在leetcode系統上可行,但是在本地運行中可能會報錯1175,解決方法是解除安全模式,具體參考? MySQL報錯之1175和1093-CSDN博客
2、這里在子查詢外層再嵌套一個查詢,因為不能同時對一個表執行子查詢后再執行刪除操作。否則會報錯1093,具體參考? MySQL報錯之1175和1093-CSDN博客
delete from Person where id not in
(select * from (select min(t1.id)
from Person as t1
group by t1.email) a);
方法二 窗口函數
用row_number(),按id升序,序號>1的就是重復且id較大的
注意事項與方法二一致
delete from Person
where id not in (
select id
from (select *,row_number() over(partition by email order by id) rowNumber
from Person) a
where rowNumber = 1
)
方法三 自連接
注意:在leetcode上成功運行,但是在本地mysql報錯1175,解決方法是解除安全模式
DELETE p1 FROM Person p1,Person p2
WHEREp1.Email = p2.Email AND p1.Id > p2.Id
方法四 臨時表實現分組
臨時表解決安全模式(1175報錯)和同時對一張表進行刪除和查詢操作(1093報錯)
注意:此方法只能在本地mysql上運行,而在leetcode上執行報錯
-- 第一步:創建臨時表存儲要刪除的 id
CREATE TEMPORARY TABLE temp_to_delete (id INT);-- 第二步:將要刪除的 id 插入到臨時表中
INSERT INTO temp_to_delete (id)
SELECT id
FROM Person
WHERE id NOT IN (SELECT MIN(id)FROM PersonGROUP BY email
);-- 第三步:使用臨時表刪除記錄
DELETE FROM Person
WHERE id IN (SELECT id FROM temp_to_delete);-- 第四步:刪除臨時表
DROP TEMPORARY TABLE temp_to_delete;