mysql實現行轉列功能

實現的功能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 ;
相關文章
相關標籤/搜索