MySQL透视表实现:将grades表课程转为列展示成绩求助
嘿,我来帮你搞定这个MySQL行列转换的问题!你要做的其实是把行数据转成列(也就是透视表),先明确下你的表结构大概是这样的(方便后续示例):
CREATE TABLE grades ( `Index number` INT, -- 注意字段名有空格,必须用反引号包裹 coursecode VARCHAR(50), grades VARCHAR(10) -- 如果是分数也可能是INT/DECIMAL类型 );
下面分两种常见场景给你解决方案:
情况1:已知所有课程代码(静态透视)
如果你的课程列表是固定的(比如只有CS101、Math202、Eng303这几门),直接用CASE WHEN配合聚合函数就能实现:
SELECT `Index number`, -- 每门课程对应一个列,用MAX过滤NULL值 MAX(CASE WHEN coursecode = 'CS101' THEN grades END) AS CS101, MAX(CASE WHEN coursecode = 'Math202' THEN grades END) AS Math202, MAX(CASE WHEN coursecode = 'Eng303' THEN grades END) AS Eng303 FROM grades GROUP BY `Index number`;
小说明:
- 这里用
MAX是因为每个学生每门课只会有一条成绩,聚合函数会自动忽略NULL值,用SUM或MIN也能达到同样效果 - 字段名
Index number有空格,必须用反引号``包裹,否则MySQL会报错
情况2:课程代码动态变化(动态透视)
如果课程会新增或者数量很多,静态写法就太麻烦了,这时候可以用动态SQL自动生成透视语句:
-- 先清空变量 SET @sql = NULL; -- 自动拼接所有课程对应的CASE语句 SELECT GROUP_CONCAT(DISTINCT CONCAT( 'MAX(CASE WHEN coursecode = ''', coursecode, ''' THEN grades END) AS `', coursecode, '`' ) ) INTO @sql FROM grades; -- 组装完整的SELECT语句 SET @sql = CONCAT('SELECT `Index number`, ', @sql, ' FROM grades GROUP BY `Index number`'); -- 执行动态SQL PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
注意事项:
- 如果课程数量特别多,可能需要调整
group_concat_max_len参数(默认长度有限),可以先执行SET SESSION group_concat_max_len = 100000;来临时扩大长度 - 动态SQL需要你有足够的数据库权限(一般WAMP默认权限是足够的)
- 如果
grades是数值类型,把MAX换成SUM或AVG都可以,结果一致
内容的提问来源于stack exchange,提问作者Manzu Gerald
相关产品推荐
相关产品推荐

