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

SQL Server 刪除完全重複資料僅保留第一筆:暫存表 + IDENTITY 法

     編輯:關於SqlServer

問題定義

資料表無主鍵/唯一約束,導致出現**完全重複列**(所有欄位值皆相同)。需刪除重複列,每組僅保留第一筆。

解法:暫存表 + IDENTITY 排序

/* 1. 建立測試資料 */
CREATE TABLE dbo.testtab (id NCHAR(10) NULL, name NCHAR(10) NULL);
INSERT INTO testtab VALUES ('1','1'), ('1','1'), ('2','2'), ('2','2'), ('3','3'), ('3','3');

/* 2. 將資料複製至暫存表並加上流水號 */
SELECT IDENTITY(INT, 1, 1) AS autoID, *
INTO #Tmp
FROM testtab;

/* 3. 刪除暫存表中每組重複資料的最後一筆(保留第一筆) */
DELETE #Tmp
WHERE autoID IN (
    SELECT MAX(autoID)
    FROM #Tmp
    GROUP BY id, name  -- 依所有業務欄位分組
);

/* 4. 清空原表並寫回去重後資料 */
DELETE testtab;
INSERT INTO testtab (id, name)
SELECT id, name FROM #Tmp;

/* 5. 清理 */
DROP TABLE #Tmp;

/* 6. 驗證 */
SELECT * FROM testtab;  -- 僅剩 3 筆

關鍵點解析

步驟目的
IDENTITY(INT,1,1)為每列產生唯一遞增序號,作為「先後順序」依據。
GROUP BY id, name定義「重複」的判斷鍵,**必須包含所有業務欄位**。
MAX(autoID)取得每組最後寫入的序號(假設先寫入者為第一筆)。
INTO #Tmp避免在原表直接操作導致鎖定升級或觸發器副作用。

替代方案比較

方法適用版本優點缺點
ROW_NUMBER() OVER (PARTITION BY ... ORDER BY ...) = 12005+單一陳述式、可保留任意順序、無需暫存表需支援視窗函數
CTE + DELETE2005+可讀性佳同左
暫存表 + IDENTITY (本文)2000+相容舊版、邏輯直觀需兩階段、鎖定較久
ALTER IGNORE TABLE ADD UNIQUE (舊 MySQL)MySQL一指令SQL Server 不支援

現代寫法(SQL Server 2005+ 推薦)

WITH cte AS (
    SELECT 
        *,
        ROW_NUMBER() OVER (PARTITION BY id, name ORDER BY (SELECT 0)) AS rn
    FROM testtab
)
DELETE FROM cte WHERE rn > 1;

預防重複資料最佳實務

  1. **定義主鍵或唯一約束**:ALTER TABLE testtab ADD CONSTRAINT PK_testtab PRIMARY KEY (id, name);
  2. **ETL 階段去重**:使用 SSIS/Azure Data Factory 的「排序/去重」元件。
  3. **MERGE UPSERT 模式**:MERGE INTO target USING source ON target.pk = source.pk WHEN NOT MATCHED THEN INSERT ...
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved