数据派
聚焦技术和人文,分享干货,共同成长。
几种去重的SQL写法
在 SQL 中,数据去重有多种实现方式,以下是几种常见写法及其适用场景:
1. 使用 DISTINCT 关键字
语法:
SELECT DISTINCT column1 [, column2, ...]
FROM table_name;
说明:直接对指定字段组合进行唯一性筛选,仅保留首次出现的记录。示例:
SELECT DISTINCT address FROM student; -- 获取不重复的地址
局限性:
若对多字段去重,需所有字段值完全相同才视为重复。
无法同时返回非去重字段的原始值,仅能展示去重字段。
2. 使用 GROUP BY 子句
语法:
SELECT column1 [, aggregate_function(column2), ...]
FROM table_name
GROUP BY column1 [, column2, ...];
说明:按指定字段分组,结合聚合函数(如 MAX、MIN、COUNT 等)获取其他字段信息。示例:
SELECT MIN(id), address FROM student GROUP BY address; -- 按地址去重,返回每组最小 id
注意:非聚合字段可能来自不同记录,导致数据逻辑上不一致(如不同 id 对应同一 address 时,聚合函数外的字段取值无明确规律)。
3. 使用窗口函数(如 ROW_NUMBER())
语法:
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY column1 ORDER BY column2) AS rn
FROM table_name
) AS t
WHERE rn = 1;
说明:先按 PARTITION BY 分组,再按 ORDER BY 排序并生成行号,筛选行号为 1 的记录。示例:
SELECT id, name, address
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY address ORDER BY id ASC) AS rn
FROM student
) AS a
WHERE a.rn = 1; -- 按地址去重,保留每组 id 最小的记录
优势:可精准控制保留哪条记录(如按时间、ID 排序取最新或最旧),但低版本 MySQL 不支持窗口函数。
4. 使用 IN 子查询
语法:
SELECT *
FROM table_name
WHERE id IN (SELECT MAX(id) FROM table_name GROUP BY column1);
说明:通过子查询找到每组唯一标识字段(如自增 id)的最大值,再筛选主表中对应记录。示例:
SELECT * FROM student WHERE id IN (SELECT MAX(id) FROM student GROUP BY address); -- 按地址去重,取每组最大 id 的记录
适用场景:表中存在唯一标识字段(如 id),且需保留特定条件(如最大 / 最小 id)的记录。
5. 使用 NOT EXISTS
语法:
SELECT a.*
FROM table_name a
WHERE NOT EXISTS (
SELECT 1 FROM table_name b
WHERE a.column1 = b.column1 AND a.id < b.id
);
示例:
SELECT a.* FROM student a WHERE NOT EXISTS (SELECT 1 FROM student b WHERE a.address = b.address AND a.id < b.id); -- 按地址去重,保留每组 id 最大的记录
逻辑:对于每一行 a,若不存在 b 行(同 column1 且 id 更大),则保留 a。
6. 使用 UNION 去重
语法:
SELECT column1 [, column2, ...]
FROM table_name1
UNION
SELECT column1 [, column2, ...]
FROM table_name2;
说明:合并多个查询结果并自动去重(UNION ALL 保留全部记录,不进行去重)。示例:
SELECT address FROM student UNION SELECT address FROM teacher; -- 合并两表地址并去重
注意:大数据量时效率较低,建议先用 UNION ALL 再结合其他方法去重。
7. 使用 INNER JOIN + GROUP BY
语法:
SELECT a.*
FROM table_name a
INNER JOIN (
SELECT column1, MAX(id) AS max_id
FROM table_name
GROUP BY column1
) b ON a.column1 = b.column1 AND a.id = b.max_id;
示例:
SELECT a.* FROM student a
INNER JOIN (SELECT address, MAX(id) AS max_id FROM student GROUP BY address) b
ON a.address = b.address AND a.id = b.max_id; -- 按地址去重,取每组最大 id 的记录
逻辑:先通过子查询获取每组最大 id,再与主表关联筛选。
实际应用中,可根据数据库特性(如是否支持窗口函数)、数据规模、业务需求(如保留特定记录)选择合适的方法。例如,简单单字段去重优先用 DISTINCT;需保留其他字段且数据一致性要求不高时用 GROUP BY;需精准控制保留记录时用窗口函数或 IN/NOT EXISTS 等。
posted on
2025-06-06 15:55
数据派
阅读(80)
评论(0)
收藏
举报
刷新页面返回顶部