如何编写SQL查询实现学生多班级数据的横向单行展示
实现学生班级数据横向展示的SQL查询方案
要把每个学生的多条班级记录横向合并到同一行(最多展示15个班级),可以用以下两种思路实现,适配不同数据库场景:
一、通用条件聚合(适配所有主流数据库)
这种方法通过给每个学生的班级记录编号,再用条件聚合把每条记录转成单独的列,最多支持15个班级:
SELECT s.StudentId, s.FirstName, s.LastName, -- 第1个班级信息 MAX(CASE WHEN c.ClassSeq = 1 THEN c.ClassId END) AS ClassId_1, MAX(CASE WHEN c.ClassSeq = 1 THEN c.ClassName END) AS ClassName_1, MAX(CASE WHEN c.ClassSeq = 1 THEN c.ClassCost END) AS ClassCost_1, -- 第2个班级信息 MAX(CASE WHEN c.ClassSeq = 2 THEN c.ClassId END) AS ClassId_2, MAX(CASE WHEN c.ClassSeq = 2 THEN c.ClassName END) AS ClassName_2, MAX(CASE WHEN c.ClassSeq = 2 THEN c.ClassCost END) AS ClassCost_2, -- 重复上述结构直到第15个班级 MAX(CASE WHEN c.ClassSeq = 15 THEN c.ClassId END) AS ClassId_15, MAX(CASE WHEN c.ClassSeq = 15 THEN c.ClassName END) AS ClassName_15, MAX(CASE WHEN c.ClassSeq = 15 THEN c.ClassCost END) AS ClassCost_15 FROM Student s LEFT JOIN ( -- 给每个学生的班级按ClassId排序生成序号 SELECT StudentId, ClassId, ClassName, ClassCost, ROW_NUMBER() OVER (PARTITION BY StudentId ORDER BY ClassId) AS ClassSeq FROM Classes ) c ON s.StudentId = c.StudentId GROUP BY s.StudentId, s.FirstName, s.LastName ORDER BY s.StudentId;
逻辑说明:
- 子查询里用
ROW_NUMBER()窗口函数,给每个学生的班级记录按ClassId排序并生成序号(ClassSeq); - 外层用
MAX(CASE...)提取对应序号的班级信息,转成单独的列; LEFT JOIN保证没有选课的学生也能出现在结果中,GROUP BY按学生维度聚合。
二、字符串聚合(简洁展示,适合不需要拆分列的场景)
如果不需要把每个班级拆成单独列,只想把所有班级信息拼接成一个字段展示,不同数据库有对应的字符串聚合函数:
MySQL 实现
SELECT s.StudentId, s.FirstName, s.LastName, GROUP_CONCAT(CONCAT('ClassId:', ClassId, ', Name:', ClassName, ', Cost:', ClassCost) SEPARATOR ' | ') AS AllClasses FROM Student s LEFT JOIN Classes c ON s.StudentId = c.StudentId GROUP BY s.StudentId, s.FirstName, s.LastName;
SQL Server(2017及以上)实现
SELECT s.StudentId, s.FirstName, s.LastName, STRING_AGG(CONCAT('ClassId:', ClassId, ', Name:', ClassName, ', Cost:', ClassCost), ' | ') AS AllClasses FROM Student s LEFT JOIN Classes c ON s.StudentId = c.StudentId GROUP BY s.StudentId, s.FirstName, s.LastName;
PostgreSQL 实现
SELECT s.StudentId, s.FirstName, s.LastName, STRING_AGG(CONCAT('ClassId:', ClassId, ', Name:', ClassName, ', Cost:', ClassCost), ' | ') AS AllClasses FROM Student s LEFT JOIN Classes c ON s.StudentId = c.StudentId GROUP BY s.StudentId, s.FirstName, s.LastName;
内容的提问来源于stack exchange,提问作者madQuestions
相关产品推荐
相关产品推荐

