| ID | Name | Age | City |
|---|---|---|---|
| 1 | 張三 | 25 | 北京 |
| 2 | 李四 | 30 | 上海 |
| 3 | 張三 | 28 | 廣州 |
| 4 | 王五 | 22 | 深圳 |
| 5 | 張三 | 25 | 北京 |
SELECT DISTINCT * FROM UserInfo;
結果:第 1 行與第 5 行完全重複,僅保留一條。第 3 行(同名不同年齡/城市)保留。
適用場景:完全重複行去重。局限:無法指定「按某幾列去重」。
SELECT * FROM (
SELECT
ROW_NUMBER() OVER (PARTITION BY Name ORDER BY ID) AS RowId,
*
FROM UserInfo
) x
WHERE x.RowId = 1;
PARTITION BY Name:按 Name 分組,組內編號從 1 開始ORDER BY ID:組內按 ID 排序,決定保留哪一行RowId = 1:每組保留第一行(最小 ID)| RowId | ID | Name | Age | City |
|---|---|---|---|---|
| 1 | 1 | 張三 | 25 | 北京 |
| 1 | 2 | 李四 | 30 | 上海 |
| 1 | 4 | 王五 | 22 | 深圳 |
「張三」三條記錄僅保留 ID=1 的那行。
SELECT
ROW_NUMBER() OVER (ORDER BY ID) AS RowNum,
*
FROM UserInfo;
結果包含連續行號 1~5,可用於:
WHERE RowNum BETWEEN 1 AND 15WHERE RowNum % 10 = 1 取 10% 樣本| 維度 | DISTINCT | ROW_NUMBER() |
|---|---|---|
| 去重粒度 | 整行 | 指定列(PARTITION BY) |
| 保留策略 | 不可控 | 可控(ORDER BY) |
| 額外能力 | 無 | 行號、分組排序、Top-N |
| 兼容性 | 所有版本 | MySQL 8.0+、SQL Server、Oracle、PostgreSQL |
| 性能 | 較快 | 窗口函數開銷稍大 |
-- 利用變量模擬 ROW_NUMBER()
SELECT * FROM (
SELECT
@row_num := IF(@prev_name = Name, @row_num + 1, 1) AS RowId,
@prev_name := Name AS Name,
ID, Age, City
FROM UserInfo, (SELECT @row_num := 0, @prev_name := '') vars
ORDER BY Name, ID
) t WHERE RowId = 1;
DISTINCT,語義清晰且高效ROW_NUMBER()ROW_NUMBER(),舊版本用 LIMIT offset, sizeGROUP BY + 聚合函數或臨時表分批處理