多对多关联查询去重:获取指定国家的唯一品牌
解决多对多关联查询中的品牌重复问题
先纠正原始查询的核心错误
你当前的SQL没有建立brands和country_brands的正确关联,只加了cb.country_id = 1的条件,这会让brands全表和所有country_id=1的关联记录做笛卡尔积,必然出现大量重复数据。正确的关联必须加上品牌ID的匹配:
SELECT b.id, b.name FROM brands b INNER JOIN country_brands cb ON b.id = cb.brand_id WHERE cb.country_id = 1;
如果此时仍有重复(比如country_brands中存在同一品牌对应同一国家的多条重复记录),可以用以下两种方法去重:
方法1:用DISTINCT直接去重
最简洁的写法,数据库会自动剔除结果集中的重复行:
SELECT DISTINCT b.id, b.name FROM brands b INNER JOIN country_brands cb ON b.id = cb.brand_id WHERE cb.country_id = 1;
方法2:用GROUP BY分组去重
注意必须按品牌的唯一主键id分组(仅按name分组风险极高,若存在重名品牌会被错误合并):
SELECT b.id, b.name FROM brands b INNER JOIN country_brands cb ON b.id = cb.brand_id WHERE cb.country_id = 1 GROUP BY b.id, b.name;
关于GROUP BY方案与关联Country表方案的性能对比
你提到的GROUP BY写法的问题
你写的GROUP BY b.name不推荐:一是会导致重名品牌被错误合并,逻辑出错;二是如果name字段没有索引,数据库需要执行大量排序分组操作,性能很差。必须依托主键id分组才能保证正确性和性能。两种方案的性能差异
- DISTINCT:先执行JOIN得到全量结果,再进行去重。适合数据量不大的场景,语法简单直观。
- GROUP BY(按主键):数据库可利用主键索引优化,在分组阶段就合并重复项,减少后续处理的数据量。如果
country_brands中重复记录较多,这种方法性能会优于DISTINCT。 - 关联Country表的方案:若不需要用到Country表的其他字段,完全没必要多这一层JOIN,会额外增加查询开销;如果需要展示国家名称等字段,再关联即可,此时性能和前面的去重方案类似,仅多一次表关联的开销。
内容的提问来源于stack exchange,提问作者Max Pattern
相关产品推荐
相关产品推荐

