重複資料清理是資料治理常態作業。本文提供針對**單欄位**、**多欄位**、**含 ROWID/主鍵**等不同場景的標準刪除腳本,並說明各資料庫(Oracle、SQL Server、MySQL、PostgreSQL)的語法差異。
-- 通用標準寫法(支援大多數資料庫)
DELETE FROM people
WHERE peopleId IN (
SELECT peopleId FROM people
GROUP BY peopleId HAVING COUNT(*) > 1
)
AND peopleId NOT IN (
SELECT MIN(peopleId) FROM people
GROUP BY peopleId HAVING COUNT(*) > 1
);
peopleId。peopleId(主鍵)。DELETE FROM vitae a
WHERE (a.peopleId, a.seq) IN (
SELECT peopleId, seq FROM vitae
GROUP BY peopleId, seq HAVING COUNT(*) > 1
)
AND a.rowid NOT IN (
SELECT MIN(rowid) FROM vitae
GROUP BY peopleId, seq HAVING COUNT(*) > 1
);
(col1, col2) IN (...)(Oracle、PostgreSQL、MySQL 8.0+ 支援)。rowid 為 Oracle 物理位址偽欄位;SQL Server 用 %%physloc%% 或主鍵;MySQL 用主鍵。-- 單欄位
SELECT * FROM people
WHERE peopleId IN (SELECT peopleId FROM people GROUP BY peopleId HAVING COUNT(*) > 1);
-- 多欄位
SELECT * FROM vitae a
WHERE (a.peopleId, a.seq) IN (
SELECT peopleId, seq FROM vitae GROUP BY peopleId, seq HAVING COUNT(*) > 1
);
| 功能 | Oracle | SQL Server | MySQL | PostgreSQL |
|---|---|---|---|---|
| 唯一列識別符 | ROWID | %%physloc%% / 主鍵 | 主鍵 | CTID / 主鍵 |
| 元組 IN | 支援 | **不支援** 用 EXISTS/JOIN | 8.0+ 支援 | 支援 |
| LIMIT 子句 | ROWNUM / FETCH FIRST | TOP / OFFSET-FETCH | LIMIT | LIMIT |
| MERGE/UPSERT | MERGE | MERGE | ON DUPLICATE KEY | ON CONFLICT |
-- 使用 CTE + ROW_NUMBER() 通用高效寫法
WITH dup AS (
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY peopleId, seq ORDER BY id) AS rn
FROM vitae
)
DELETE FROM dup WHERE rn > 1;
PARTITION BY 定義重複群組。ORDER BY 決定保留哪一列(如最小 id)。rn > 1 刪除群組內其餘列。WITH dup AS (
SELECT id, ROW_NUMBER() OVER (PARTITION BY peopleId ORDER BY id) AS rn
FROM people
)
DELETE p FROM people p JOIN dup d ON p.id = d.id WHERE d.rn > 1;
DELETE FROM vitae
WHERE ROWID NOT IN (
SELECT MIN(ROWID) FROM vitae
GROUP BY peopleId, seq HAVING COUNT(*) > 1
)
AND (peopleId, seq) IN (
SELECT peopleId, seq FROM vitae GROUP BY peopleId, seq HAVING COUNT(*) > 1
);
DELETE TOP (10000) ... (SQL Server) 或 LIMIT 10000 (MySQL),循環直到 @@ROWCOUNT = 0。CREATE TABLE new AS SELECT DISTINCT ... FROM old → 重建索引/約束 → RENAME,速度最快、日誌最少。ALTER TABLE ... EXCHANGE PARTITION 快速清理。ALTER TABLE ADD UNIQUE (col1, col2),源頭阻擋。ROW_NUMBER() 或 DISTINCT 清洗。INSERT ... ON DUPLICATE KEY UPDATE / MERGE。選擇適合資料庫版本與資料量的方案,配合唯一約束預防,建立「清理-預防」閉環治理體系。