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();
方法分析:
第一种方法使用了表连接。
第二种使用了分组,对每个分组分别处理。
第三种使用了存储过程,其实是第二种方法的动态化,先计算出所有课程的数量,然后对每个分组进行课程查询。
很明显前两种方法属于硬编码,增加课程后就需要修改SQL。而第三种则没有这种问题。
Note:
MySQL中不能在一个存储过程中删除另一个存储过程,只能调用另一个存储过程
本来想在方法三里面写上:DROP PROCEDURE IF EXISTS sp_count();这是错误的。调试的时候如果写错了,只能手动删除了,也没找到好方法。
方法二还可以使用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
- IF(expr1,expr2,expr3),如果expr1是TRUE(expr1<>0且expr1<>NULL),那么IF()返回expr2,否则它返回expr3。IF()返回一个数字或字符串值,取决于它被使用的上下文。