實現的功能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 ;