2021-06-07 11:30

MySQL数据库,行列转换

码自答

数据库

(901)

(1)

收藏

数据库数据行列转换。

本文以MySQL8.0数据库为例。

新建student_manage数据库,新建exam表,表中间保存学生的姓名,科目和成绩。

image.png

数据库表中间的数据如下图:

image.png

现在想将表中间的数据全部查出。但是显示的格式希望如下图:

image.png

将表中间的数据进行行列的转换。

如果已知科目只有数学,物理,化学三科

方案一:

通过if完成

SELECT NAME,
sum(if(course='数学',scores,0)) AS 数学,
sum(if(course='物理',scores,0)) AS 物理,
sum(if(course='化学',scores,0)) AS 化学,
SUM(scores) AS 总分,
round(AVG(scores),2) AS 平均分
FROM exam GROUP BY name

image.png

按照学生姓名相同的分成一组,分别计算每组的数学成绩,物理成绩,化学成绩的总和。

如果不加sum聚合函数求和,计算的仅仅只是每组中间的第一条记录。

如果不加sum聚合函数,在其他数据库中间直接是语法错误。


方案二:

通过case完成

SELECT NAME,
SUM(case course when '数学' then scores ELSE 0 END) AS 数学,
SUM(case course when '物理' then scores ELSE 0 END) AS 物理,
SUM(case course when '化学' then scores ELSE 0 END) AS 化学,
SUM(scores) AS 总分,
round(AVG(scores),2) AS 平均分
FROM exam GROUP BY name

和if处理的思路基本一致。

image.png

如果该行科目是数学,计算该行成绩,否则,该行成绩为0。

也可以写成如下代码。

image.png

和if只是语法不同,处理思路是相同的。


如果表中间的数据科目不确定,不知道由多少行。

也就是以上两种处理方案中间的if和case出现的次数不确定。那么只能先查出表中间的所有的科目,通过科目的查询结果,来拼接if或者case的语句。

代码如下:

SET @sql_string='';
/*声明@sql_string变量  其值为空字符串*/
SELECT @sql_string:=CONCAT(@sql_string,'sum(if(course= \'',course,'\',scores,0)) as ',course, ',') AS str FROM
/*因为temp有3条记录  数学 物理 化学  所以以上的拼接语句会执行3次*/

(SELECT DISTINCT course FROM exam)AS temp ;
/*查出所有的course 科目 本例题 三个科目 数学 物理 化学  */
/*@sql_string的值为  sum(if(course='数学',scores,0)) as 数学,sum(if(course='物理',scores,0))as 物理,sum....,*/
/*会有,作为结尾*/

SET @sql_string = CONCAT('select name,',@sql_string,' sum(scores) as 总分,round(avg(scores),2) as 平均分 from exam group by name');
/*给变量@sql_string变量赋值*/
/*拼接成为一条完整的sql语句 */
/*@sql_string的值为  select name,sum(if(course='数学',scores,0)) as 数学,sum(if(course='物理',scores,0)) as .....*/
/*@sql_string是一个字符串*/

PREPARE test FROM @sql_string;/*预定义sql语句*/
EXECUTE test;/*执行sql语句*/
DEALLOCATE PREPARE test;/*释放资源*/
/*prepare execute deallocate 预处理语句*/


image.png

image.png

如果course是数学,就变成

'sum(if(course= \'数学\',scores,0)) as 数学,'

1条评论

点击登录参与评论

  • author
    码自答 2021-06-07 11:31

    Oracle的行列转换: Oracle SELECT * FROM exam PIVOT(sum(scores) FOR course IN ('数学','物理','化学'))