如何高效处理多列需唯一的大表SQL JOIN操作?
处理LEFT JOIN后重复行的高效方案
问题背景
现有两张表(示例如下),需通过ID执行LEFT JOIN后得到含唯一行的结果表,最终需保留26001行(包含所有ID为0的空行)。当前表有30+列、约25k行,直接执行LEFT JOIN会产生大量重复行且耗时久,纠结是否需要GROUP BY所有列、使用更高效的方式(比如GROUP ALL),或是用DISTINCT处理所有列。
示例表
table1
ID art1 art2 1 90 20 2 20 80 3 20 20
table2
ID art1 art2 1 20 20 2 40 30 4 20 50
期望结果(顺序无关)
ID art1 art2 1 ... 2 3 4
低效的原查询
SELECT * FROM `table1` LEFT JOIN `table2` USING (ID)
考虑中的修改方案
SELECT * FROM `table1` LEFT JOIN `table2` USING (ID) GROUP BY *insert all columns?*
解决方案
LEFT JOIN产生重复行的核心原因是某张表中存在重复的ID值——比如table1或table2里同一个ID对应多行数据,JOIN后会生成笛卡尔积导致重复。针对需求,给出几个高效方案:
先去重再JOIN(最优选择)
不要先JOIN再去重,而是先对存在重复ID的表做去重处理,再执行JOIN,能大幅减少数据量、提升效率:- 若table2存在重复ID:
SELECT t1.*, t2.* FROM `table1` t1 LEFT JOIN ( SELECT DISTINCT ID, art1, art2 -- 列出table2所有需要的列 FROM `table2` ) t2 USING (ID) - 若不确定哪张表有重复,两张表都先去重:
SELECT t1.*, t2.* FROM ( SELECT DISTINCT ID, art1, art2 -- 列出table1所有列 FROM `table1` ) t1 LEFT JOIN ( SELECT DISTINCT ID, art1, art2 -- 列出table2所有列 FROM `table2` ) t2 USING (ID)
- 若table2存在重复ID:
用DISTINCT替代GROUP BY所有列
如果必须先JOIN再去重,SELECT DISTINCT *比GROUP BY所有列更简洁,效率也相近(大部分数据库优化器会将两者处理为相同执行计划):SELECT DISTINCT * FROM `table1` LEFT JOIN `table2` USING (ID)关于GROUP ALL的说明
GROUP ALL是部分数据库(如PostgreSQL)的语法,它会保留所有分组(哪怕分组内无匹配行),但本质和普通GROUP BY不同——若目标是去重,GROUP ALL无法直接解决问题,反而需要配合聚合函数(如MAX(art1)),这会改变原始数据,不符合保留所有行的需求,因此不建议使用。
关键提醒
- LEFT JOIN本身会保留table1的所有行,包括ID为0的空行;若table2中也有ID为0的行,先去重即可避免重复。
- 针对30+列的场景,不管是DISTINCT还是子查询中的DISTINCT,用
*即可(部分数据库有语法限制时,需手动列出所有列,主流数据库均支持*写法)。
内容的提问来源于stack exchange,提问作者R4lfXD
相关产品推荐
相关产品推荐

