機場資料表 airport,欄位:id (PK), name, c_name, code (三字碼), city_name。業務要求 code 唯一,但爬蟲抓取產生重複三字碼,需清洗後再加唯一索引。
CREATE TABLE airport (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100),
c_name VARCHAR(100),
code CHAR(3) NOT NULL,
city_name VARCHAR(100)
);
SHOW INDEX FROM airport;
DROP INDEX code ON airport;
邏輯:同一 code 下,保留 MAX(id),刪除其餘。
-- 先建臨時表存放待刪除 ID
CREATE TEMPORARY TABLE tmp_dup AS
SELECT id FROM airport
WHERE id IN (
SELECT id FROM airport
GROUP BY code HAVING COUNT(*) > 1
)
AND id NOT IN (
SELECT MAX(id) FROM airport
GROUP BY code HAVING COUNT(*) > 1
);
為什麼用臨時表? MySQL 不允許在同一語句中既查詢又修改同一張表(You can't specify target table for update in FROM clause)。
DELETE FROM airport WHERE id IN (SELECT id FROM tmp_dup);
SELECT code, COUNT(*) FROM airport GROUP BY code HAVING COUNT(*) > 1;
-- 應返回空集合
ALTER TABLE airport ADD UNIQUE INDEX uk_code (code);
WITH to_delete AS (
SELECT id FROM airport
WHERE id IN (
SELECT id FROM airport GROUP BY code HAVING COUNT(*) > 1
)
AND id NOT IN (
SELECT MAX(id) FROM airport GROUP BY code HAVING COUNT(*) > 1
)
)
DELETE a FROM airport a JOIN to_delete d ON a.id = d.id;
code 上有索引(即使非唯一),加速 GROUP BY。pt-archiver 或建新表 INSERT ... SELECT DISTINCT ON (code) ... 切換。