多表LEFT JOIN查询学生班级信息出现重复结果问题咨询
问题背景
现有3张业务数据表,结构如下:
students(id, name):存储学生基础信息student_class_relation(id, student_id, class_id):存储学生和班级的关联关系class(id, class_name, block):存储班级基础信息
业务规则为一名学生可关联多个班级,查询需求为获取全量学生记录,同时关联返回对应班级的名称、block等班级详情。
当前执行查询时出现学生记录重复问题:一名学生关联多少个班级,查询结果中就会生成多少条该学生的重复行,每行对应一个关联班级。当前使用的SQL语句如下:
select students.name,class.name, class.block from students left join student_class_relation on student_class_relation.student_id=students.id left join class on class.id=student_class_relation.class_id
问题原因
重复是多对多关联查询的正常表现:LEFT JOIN会逐行返回所有满足关联条件的匹配结果,1个学生对应N条班级关联记录时,自然会生成N行该学生的结果。
解决方法
如果需要每个学生仅返回1条记录,将同个学生关联的多个班级信息聚合到同一行即可,根据使用的数据库选择对应的字符串聚合函数实现:
以MySQL为例,使用GROUP_CONCAT函数拼接同组的班级信息,同时按学生维度分组即可去重:
SELECT students.name AS student_name, GROUP_CONCAT(class.class_name SEPARATOR '、') AS related_class_names, GROUP_CONCAT(class.block SEPARATOR '、') AS related_class_blocks FROM students LEFT JOIN student_class_relation ON student_class_relation.student_id = students.id LEFT JOIN class ON class.id = student_class_relation.class_id GROUP BY students.id, students.name;
其他数据库对应替换聚合函数即可:
- PostgreSQL、SQL Server 2017及以上版本使用
STRING_AGG - Oracle使用
LISTAGG
如果业务要求每个班级信息单独占用一个字段而非拼接展示,需要先明确单个学生最多关联的班级数量,再通过行转列逻辑实现,该类场景实际使用较少。
内容的提问来源于stack exchange,提问作者Vishnu Roshan
相关产品推荐
相关产品推荐

