如何转换SQL表?用PIVOT实现无限行有限列的表结构转置
课程表行转固定列的SQL实现方案
你的需求是将行式存储的课程数据,转换为以课程节次为行、周一到周五为固定列的矩阵结构,这种场景完全可以通过SQL实现,不管课程节次的行数有多少,只要目标列固定(周一到周五)就没问题。下面提供两种通用方案:
方法一:条件聚合(兼容绝大多数数据库)
这是最通用的实现方式,适用于MySQL、SQL Server、PostgreSQL等几乎所有主流数据库:
SELECT NumberOfLesson, COALESCE(MAX(CASE WHEN DayOfWeek = '周一' THEN LessonName END), '0') AS 周一, COALESCE(MAX(CASE WHEN DayOfWeek = '周二' THEN LessonName END), '0') AS 周二, COALESCE(MAX(CASE WHEN DayOfWeek = '周三' THEN LessonName END), '0') AS 周三, COALESCE(MAX(CASE WHEN DayOfWeek = '周四' THEN LessonName END), '0') AS 周四, COALESCE(MAX(CASE WHEN DayOfWeek = '周五' THEN LessonName END), '0') AS 周五 FROM 你的课程表名 GROUP BY NumberOfLesson ORDER BY NumberOfLesson;
代码说明:
- 用
CASE语句针对每个星期筛选对应课程名称,没有课程的情况会返回NULL MAX聚合函数确保每个(节次,星期)组合只返回一个值(符合一个节次在同一星期不会有多门课的业务逻辑)COALESCE将NULL替换为你需要的'0',表示该时段无课
方法二:PIVOT语法(仅支持SQL Server、Oracle等支持PIVOT的数据库)
如果你使用的数据库支持PIVOT语法,可以用更简洁的写法:
SELECT NumberOfLesson, ISNULL([周一], '0') AS 周一, ISNULL([周二], '0') AS 周二, ISNULL([周三], '0') AS 周三, ISNULL([周四], '0') AS 周四, ISNULL([周五], '0') AS 周五 FROM (SELECT NumberOfLesson, DayOfWeek, LessonName FROM 你的课程表名) AS SourceTable PIVOT ( MAX(LessonName) FOR DayOfWeek IN ([周一], [周二], [周三], [周四], [周五]) ) AS PivotTable ORDER BY NumberOfLesson;
代码说明:
- 先构造源数据子查询,再通过
PIVOT将DayOfWeek的固定值转成列 MAX用于聚合去重,保证每个(节次,星期)组合唯一ISNULL将无课的空值替换为'0'
补充说明
- 两种方案都支持任意数量的课程节次,新增节次会自动作为新行出现在结果中
- 如果需要显示所有可能的节次(哪怕某节次全周无课),可以先通过递归CTE生成一个包含所有节次的临时表,再与上述结果做左连接,确保无课的节次也能显示
内容的提问来源于stack exchange,提问作者Polikarpos Goldshtein
相关产品推荐
相关产品推荐

