学校里面记录成绩,每一个人的选课不同,并且之后会添加课程,因此不须要把全部课程看成列。数据库grade里面数据以下图,假定每一个人姓名都不同,做为主键。本文以MySQL为基础,其余数据库会有些许语法不一样。 html
下面介绍三种方法: 编码
方法一: spa
SELECTDISTINCT a.name, (SELECTscoreFROMgrade bWHEREa.name=b.nameANDb.course='语文')AS'语文', (SELECTscoreFROMgrade bWHEREa.name=b.nameANDb.course='数学')AS'数学', (SELECTscoreFROMgrade bWHEREa.name=b.nameANDb.course='英语')AS'英语' FROMgrade a
方法二: 调试
SELECTname, SUM(CASE courseWHEN '语文'THENscoreEND)AS'语文', SUM(CASE courseWHEN '数学'THENscoreEND)AS'数学', SUM(CASE courseWHEN '英语'THENscoreEND)AS'英语' FROMgradeGROUPBYname
方法三: code
DELIMITER && CREATE PROCEDURE sp_count() BEGIN #课程名称 DECLARE course_n VARCHAR(20); #全部课程数量 DECLARE count INT; #计数器 DECLARE i INT DEFAULT 0; #拼接SQL字符串 SET @s = 'SELECT name'; SET count = (SELECT COUNT(distinct course) FROM grade); WHILE i < count DO SET course_n = (SELECT course FROM grade LIMIT i,1); SET @s = CONCAT(@s, ', SUM(CASE course WHEN ','\'', course_n,'\'',' THEN score END )',' AS ','\'',course_n,'\''); SET i = i+1; END WHILE; SET @s = CONCAT(@s, ' FROM grade GROUP BY name'); #用于调试 #SELECT @s; PREPARE stmt FROM @s; EXECUTE stmt; END && call sp_count();
方法分析: htm
第一种方法使用了表链接。
第二种使用了分组,对每一个分组分别处理。
第三种使用了存储过程,实际上是第二种方法的动态化,先计算出全部课程的数量,而后对每一个分组进行课程查询。
很明显前两种方法属于硬编码,增长课程后就须要修改SQL。而第三种则没有这种问题。 blog
Note: 字符串
MySQL中不能在一个存储过程当中删除另外一个存储过程,只能调用另外一个存储过程
原本想在方法三里面写上:DROP PROCEDURE IF EXISTS sp_count();这是错误的。调试的时候若是写错了,只能手动删除了,也没找到好方法。
参考资料:
2013-8-8更新:
方法二还可使用IF语句。
以下所示:
SELECT name, SUM(IF (course = '语文' , score , null ) ) as '语文', SUM(IF (course = '数学' , score , null ) ) as '数学', SUM(IF (course = '英语' , score , null ) ) as '英语 ' FROM grade GROUP BY name