DELETE FROM zqzrdp WHERE tel IN (
SELECT MIN(dpxx_id) FROM zqzrdp GROUP BY tel HAVING COUNT(tel) > 1
);
報錯:You can't specify target table 'zqzrdp' for update in FROM clause
MySQL 不允許在同一語句中既更新目標表又從該表讀取子查詢。
DELETE a
FROM test1 a
JOIN (
SELECT subject, receiver, MAX(id) AS max_id
FROM test1
WHERE status = 0
GROUP BY receiver, subject
HAVING COUNT(*) > 1
) b ON a.subject = b.subject AND a.receiver = b.receiver AND a.id < b.max_id;
-- 1. 建立臨時表存儲要保留的主鍵 CREATE TEMPORARY TABLE tmp_keep AS SELECT MIN(id) AS id FROM zqzrdp GROUP BY tel HAVING COUNT(*) > 1; -- 2. 刪除不在保留集合中的重複行 DELETE FROM zqzrdp WHERE tel IN (SELECT tel FROM zqzrdp GROUP BY tel HAVING COUNT(*) > 1) AND id NOT IN (SELECT id FROM tmp_keep);
ALTER TABLE zqzrdp ADD autoID INT AUTO_INCREMENT NOT NULL; CREATE TABLE tmp SELECT MIN(autoID) AS autoID FROM zqzrdp GROUP BY Name, Address; CREATE TABLE tmp2 SELECT zqzrdp.* FROM zqzrdp JOIN tmp ON zqzrdp.autoID = tmp.autoID; DROP TABLE zqzrdp; RENAME TABLE tmp2 TO zqzrdp;
WITH ranked AS (
SELECT id, tel,
ROW_NUMBER() OVER (PARTITION BY tel ORDER BY id) AS rn
FROM zqzrdp
)
DELETE FROM zqzrdp
WHERE id IN (SELECT id FROM ranked WHERE rn > 1);
ALTER IGNORE TABLE zqzrdp ADD UNIQUE INDEX uk_tel (tel);
IGNORE 會自動刪除重複行(保留第一行)| 場景 | 推薦方案 | 理由 |
|---|---|---|
| 小/中表、一次性清理 | 方案二 (臨時表) | 語法標準、易驗證、風險低 |
| 大表、有維護窗口 | 方案三 (新表重建) | 速度最快、無碎片、可並行 |
| MySQL 8.0 線上業務 | 方案四 (CTE + 窗口函數) | 單語句、無鎖表、可分批 |
| 日常防重 | 加唯一索引 + 捕獲 Duplicate Key 錯誤 | 源頭治理、零性能損耗 |