表 book:
id | author | title
1 | aaa | AAA
2 | bbb | BBB
3 | ccc | CCC
4 | ddd | DDD
5 | eee | AAA
需求:依 title 去重,保留完整欄位(如取第一筆或最後一筆)。
SELECT DISTINCT title, author FROM book 仍會回傳 5 筆,因 DISTINCT 作用於所有選取欄位組合。
SELECT a.*
FROM book a
RIGHT JOIN (
SELECT MIN(id) AS id FROM book GROUP BY title
) b ON b.id = a.id
WHERE a.id IS NOT NULL;
SELECT a.*
FROM book a
RIGHT JOIN (
SELECT MAX(id) AS id FROM book GROUP BY title
) b ON b.id = a.id
WHERE a.id IS NOT NULL;
GROUP BY title 取每組極值 id。JOIN 回主表撈完整欄位。RIGHT JOIN 確保即使主表無對應也保留子查詢結果(理論上不會發生)。WITH ranked AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY title ORDER BY id) AS rn
FROM book
)
SELECT id, author, title FROM ranked WHERE rn = 1;
PARTITION BY title 分組。ORDER BY id 決定取第一筆或最後一筆(DESC 取最後)。title 上建立索引:CREATE INDEX idx_title ON book(title);SELECT DISTINCT *,必須明確列出欄位。| 錯誤寫法 | 原因 |
|---|---|
SELECT DISTINCT title, * FROM book | 語法錯誤,DISTINCT 不支援 * |
SELECT DISTINCT title, author FROM book | 若 author 不同,仍會回傳多筆 |
GROUP BY title 直接選其他欄位 | MySQL ONLY_FULL_GROUP_BY 模式下報錯;非標準 SQL 行為不可攜 |
掌握子查詢極值 JOIN 或窗口函數,即可精準取得「欄位去重且保留完整列」的結果。