首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

SQL Server 刪除重複資料:完全重複與部分重複兩大場景解法

     編輯:MySQL 資料庫相關知識

資料表出現重複列是常見資料品質問題。依重複定義不同,解法分為「完全重複」與「部分重複」兩類,本文提供標準 T-SQL 寫法。

場景一:完全重複 (所有欄位值皆相同)

-- 建立測試資料
CREATE TABLE #tmp (UserID INT, Name VARCHAR(10), Age INT);
INSERT INTO #tmp VALUES 
(111,'張三',26),(222,'李四',25),(333,'王五',30),(111,'張三',26);

-- 解法:DISTINCT 去重
SELECT DISTINCT * FROM #tmp;

-- 若需保留至正式表
SELECT DISTINCT * INTO #new FROM #tmp;
DROP TABLE #tmp;
EXEC sp_rename '#new', '#tmp';

場景二:部分重複 (關鍵欄位重複,但非關鍵欄位如日期不同)

-- 測試資料:同一用戶有多筆不同日期記錄
CREATE TABLE #t (UserID INT, Name VARCHAR(10), Age INT, LogDate DATETIME);
INSERT INTO #t VALUES 
(111,'張三',26,'2010-02-23'),
(222,'李四',25,'2010-03-13'),
(333,'王五',30,'2011-03-25'),
(111,'張三',26,'2011-07-07');

-- 需求:同 UserID+Name+Age 視為重複,保留「日期最新」那一筆
-- 解法:NOT EXISTS 相關子查詢
SELECT * FROM #t a
WHERE NOT EXISTS (
    SELECT 1 FROM #t b
    WHERE b.UserID = a.UserID
      AND b.Name   = a.Name
      AND b.Age    = a.Age
      AND b.LogDate > a.LogDate
);

進階:使用 ROW_NUMBER() (SQL Server 2005+)

WITH cte AS (
    SELECT *,
           ROW_NUMBER() OVER (
               PARTITION BY UserID, Name, Age 
               ORDER BY LogDate DESC
           ) AS rn
    FROM #t
)
DELETE FROM cte WHERE rn > 1;

效能建議

  • 資料量 < 10 萬筆:NOT EXISTS 或 DISTINCT 即可。
  • 資料量 > 10 萬筆:建議加上關鍵欄位索引,或使用 ROW_NUMBER() 搭配 CTE 刪除,效能較佳。
  • 正式環境刪除前,務必先 備份 或用 SELECT 驗證結果集正確性。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved