資料表 contact 中 userid 有重複值,需刪除重複列,僅保留 id 最小(最早建立)的那一筆。
DELETE FROM contact
WHERE id IN (
SELECT c1.id
FROM contact c1
INNER JOIN contact c2
ON c1.userid = c2.userid
AND c1.id > c2.id
);
| userid | id | 動作 |
|---|---|---|
| 100 | 1 | 保留 (最小 id) |
| 100 | 5 | 刪除 (存在 id=1 同 userid 且 5 > 1) |
| 100 | 9 | 刪除 (存在 id=1 同 userid 且 9 > 1) |
| 200 | 2 | 保留 |
| 200 | 7 | 刪除 |
WITH cte AS (
SELECT id, ROW_NUMBER() OVER (PARTITION BY userid ORDER BY id) AS rn
FROM contact
)
DELETE FROM cte WHERE rn > 1;
ORDER BY id DESC 保留最新、ORDER BY created_at 依時間。DECLARE @batch INT = 5000, @deleted INT = 1;
WHILE @deleted > 0
BEGIN
DELETE TOP (@batch) FROM contact
WHERE id IN (
SELECT c1.id FROM contact c1
INNER JOIN contact c2 ON c1.userid = c2.userid AND c1.id > c2.id
);
SET @deleted = @@ROWCOUNT;
WAITFOR DELAY '00:00:01'; -- 降低鎖衝突
END
自我聯結刪除重複是經典技巧,但現代資料庫請優先使用 ROW_NUMBER() 視窗函數,配合 CTE 寫法,程式碼更易讀、維護與效能調優。