实现的功能sql
在实现报表类的业务功能时数据库存储的表结构可能须要转换(这里须要每一行记录中都保存单个学生的全部课程成绩)数据库
本文用常见的学生表,成绩表来实现函数
初始的表结构 ui
图一code
须要实现的功能开发
图二input
建表SQL数学
学生表 模板
CREATE TABLE `student` ( `stuid` varchar(16) NOT NULL COMMENT '学号', `stunm` varchar(20) NOT NULL COMMENT '学生姓名', PRIMARY KEY (`stuid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
课程表class
CREATE TABLE `courses` ( `courseno` varchar(20) NOT NULL, `coursenm` varchar(100) NOT NULL, `teacherNo` varchar(20) DEFAULT NULL, PRIMARY KEY (`courseno`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='课程表'
成绩表
CREATE TABLE `score` ( `stuid` varchar(16) NOT NULL, `courseno` varchar(20) NOT NULL, `scores` float DEFAULT NULL, PRIMARY KEY (`stuid`,`courseno`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
实现过程
1 咱们须要将三表关联 构造出一个含有学生名,课程名,分数的基表
SELECT s.`stunm`, c.`coursenm`, sc.`scores` FROM student s LEFT JOIN score sc ON s.`stuid` = sc.stuid LEFT JOIN courses c ON sc.`courseno` = c.`courseno`
2 要实如今每一行中展示学生的全部成绩,应当根据构造出的表中的学生来分组
SELECT stunm,MAX(CASE WHEN coursenm ='大学语文' THEN scores ELSE 0 END) AS'大学语文' , MAX(CASE WHEN coursenm ='新视野英语' THEN scores ELSE 0 END) AS'新视野英语' , MAX(CASE WHEN coursenm ='离散数学' THEN scores ELSE 0 END) AS'离散数学' , MAX(CASE WHEN coursenm ='几率论与数理统计' THEN scores ELSE 0 END) AS'几率论与数理统计' , MAX(CASE WHEN coursenm ='线性代数' THEN scores ELSE 0 END) AS'线性代数' , MAX(CASE WHEN coursenm ='高等数学(一)' THEN scores ELSE 0 END) AS'高等数学(一)', MAX(CASE WHEN coursenm ='高等数学(四)' THEN scores ELSE 0 END) AS'高等数学(四)' FROM (SELECT s.`stunm`, c.`coursenm`, sc.`scores` FROM student s LEFT JOIN score sc ON s.`stuid` = sc.stuid LEFT JOIN courses c ON sc.`courseno` = c.`courseno` ) a GROUP BY stunm
group by 语句 在数据库表中 根据group by 的字段 进行分组
MAX(CASE WHEN coursenm ='大学语文' THEN scores ELSE 0 END) AS'大学语文'
这条语句的目的是 获得某个学生大学语文的成绩(好比 : 张三 ,咱们知道在聚合以前名字为张三的数据记录有7(总共七门课程)条,聚合时对这七条数据作处理 若是课程名是大学语文 则返回对应的成绩 若是不是则设为0 这样max 配合case when 语句就获得了某个学生的语文成绩了),其余课程相似,这样咱们获得了所要的结果。
动态拼接查询表头
这里咱们意识到 咱们是知道全部课程名才能这样处理,实际开发中这个条件咱们是不知道的,也就是说要考虑动态的状况 咱们看到查询的标题数据格式差很少跟数据库中的课程名字段相关
好吧我么能够这样来实现,要用到一个函数
GROUP_CONCAT
SELECT GROUP_CONCAT( 'max(case when coursenm = trim(\'', coursenm, '\') then scores else 0 end ) as \'', coursenm, '\'' ) FROM courses
这样就能实现表头的结构
存储过程实现
附上个人存储过程通用模板
USE `proceduretest`$$ DROP PROCEDURE IF EXISTS `paramtest`$$ CREATE PROCEDURE `paramtest`( IN inputid INT ,OUT outputid INT, INOUT iando INT ) BEGIN END$$ DELIMITER ;
这里存储过程的实现只传入学生ID就能够了查询语句须要拼接
DELIMITER $$ DROP PROCEDURE IF EXISTS `linetorowhen`$$ CREATE DEFINER=`root`@`localhost` PROCEDURE `linetorowhen`(IN stuid INT) BEGIN SET @querySql = NULL ; SET @stuid = NULL ; -- 拼接查询标头 SELECT GROUP_CONCAT( 'max(case when coursenm = trim(\'',-- 去空格 \用来转义 coursenm, '\') then scores else 0 end ) as \'', coursenm, '\'' ) INTO @querySql FROM courses; SET @querySql = CONCAT('select stunm,',@querySql, ' FROM (SELECT s.stunm, c.coursenm, sc.scores FROM student s LEFT JOIN score sc ON s.stuid = sc.stuid LEFT JOIN courses c ON sc.courseno = c.courseno ' ) ; -- 传入查询条件是否包含学号 不包含则所有查询 IF stuid IS NOT NULL AND stuid != '' THEN SET @stuid = stuid ; SET @querySql = CONCAT( @querySql, ' where s.stuid = trim( \'', @stuid, '\' )' ) ; END IF ; SET @querySql = CONCAT(@querySql, ') a GROUP BY stunm') ; PREPARE stmt FROM @querySql ; EXECUTE stmt ; DEALLOCATE PREPARE stmt ; END$$ DELIMITER ;