首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

單一 SQL 刪除重複資料並保留最舊記錄:自我聯結法

     編輯:關於SqlServer

問題

資料表 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
);

原理圖解

useridid動作
1001保留 (最小 id)
1005刪除 (存在 id=1 同 userid 且 5 > 1)
1009刪除 (存在 id=1 同 userid 且 9 > 1)
2002保留
2007刪除

等效現代寫法(SQL Server 2005+ / Oracle / PostgreSQL / MySQL 8.0+)

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 寫法,程式碼更易讀、維護與效能調優。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved