1. 程式人生 > >[MySQL] 行列轉換變化各種方法實現總結(行變列報表統計、列變行資料記錄統計等)

[MySQL] 行列轉換變化各種方法實現總結(行變列報表統計、列變行資料記錄統計等)

前言:

mysql行列變化,最難的就是將多個列變成多行,使用的比較多的是統計學中行變列,列變行,沒有找到現成的函式或者語句,所以自己寫了儲存過程,使用動態sql來實現,應用業務場景,使用者每個月都有使用記錄數錄入一張表,一個月一個欄位,所以表的欄位是動態增長的,現在需要實時統計當前使用者使用的總數量,如果你知道有多少個欄位,那麼可以用select c1+c2+c3+…. From tbname where tid=’111’;來實現,但是關鍵是這個都是動態的,所以在應用程式端來實現確實不適宜,可以放在資料庫後臺在儲存過程裡實現。

而且在行變成列中,如果要寫單個sql來實現,列的數目就需要寫死,因為如果不知道要展示成多少列的話,就需要用動態變數,而一條

sql裡面無法使用動態變數。但是可以使用sql塊來實現動態的效果。
  

一,列變成行例子演示

1,準備測試資料

這是基礎資料表,裡面有多個欄位wm201403……,現在需要把N個這樣的列變成行資料。

USE csdn;
DROP TABLE IF EXISTS flow_table;
CREATE TABLE `flow_table` (
  `ID` INT(11) NOT NULL AUTO_INCREMENT,
  `Number` BIGINT(11) NOT NULL,
  `City` VARCHAR(10) NOT NULL,
  `wm201403` DECIMAL(7,2) DEFAULT NULL,
  `wm201404` DECIMAL(7,2) DEFAULT NULL,
  `wm201405` DECIMAL(7,2) DEFAULT NULL,
  `wm201406` DECIMAL(7,2) DEFAULT NULL,
  `wm201407` DECIMAL(7,2) DEFAULT NULL,
  `wm201408` DECIMAL(7,2) DEFAULT NULL,
  PRIMARY KEY (`ID`,`Number`)
) ENGINE=INNODB   DEFAULT CHARSET=utf8;

錄入一批測試資料:

INSERT INTO flow_table(Number,City,wm201403,wm201404,wm201405,wm201406,wm201407,wm201408)SELECT 1,'shanghai',100.2,180.4,141,164,124,127;
INSERT INTO flow_table(Number,City,wm201403,wm201404,wm201405,wm201406,wm201407,wm201408)SELECT 2,'shanghai',110.23,180.34,141.23,104.78,124.67,127.45;
INSERT INTO flow_table(Number,City,wm201403,wm201404,wm201405,wm201406,wm201407,wm201408)SELECT 3,'beijing',123.23,110.34,131.33,154.58,154.67,167.45;
INSERT INTO flow_table(Number,City,wm201403,wm201404,wm201405,wm201406,wm201407,wm201408)SELECT 4,'hangzhou',0,110.34,131.33,154.58,154.67,0;
INSERT INTO flow_table(Number,City,wm201405,wm201406,wm201407,wm201408)SELECT 5,'hangzhou',131.33,154.58,154.67,0;

需要達到的統計效果是:

+--------+-----------+

| Number | total_num |

+--------+-----------+

|      1 |    836.60 |

|      2 |    788.70 |

|      3 |    841.60 |

|      4 |    550.92 |

|      5 |    440.58 |

+--------+-----------+

5 rows in set (0.00 sec)

2,儲存過程遍歷:

這個儲存過程建立了2張臨時表,查詢測試表資料形成遊標,遍歷遊標根據主鍵Number來呼叫pro_flow_modify儲存過程進行行列變化。程式碼如下:

DELIMITER $$
DROP PROCEDURE IF EXISTS csdn.`proc_all_changes`$$
CREATE PROCEDURE csdn.proc_all_changes()
BEGIN
    DECLARE v_number BIGINT;
    DECLARE v_city VARCHAR(10);
    DECLARE _done INT DEFAULT 0; 
    
    /*定義遊標*/
    DECLARE cur_all CURSOR FOR SELECT Number,City FROM csdn.`flow_table`;
    /**這裡如果需要定義下當NOT FOUND的時候,EXIT退出遊標遍歷,不然如果設定成CONTINUE會一直執行下去。*/
    DECLARE EXIT HANDLER FOR NOT FOUND BEGIN SET _done=1;END;      
    
       /*建立臨時表,存放所有欄位的臨時表*/
	DROP TABLE IF EXISTS flow_n_columns;
	CREATE TABLE `flow_n_columns` (
	  `column_name` VARCHAR(10) NOT NULL
	) ENGINE=INNODB DEFAULT CHARSET=utf8;

	/*存放最終變成行的資料表*/
	DROP TABLE IF EXISTS flow_tmp;
	CREATE TABLE `flow_tmp` (
	  `Number` INT(11) DEFAULT NULL,
	  `City` VARCHAR(10) DEFAULT NULL,
	  `wm_str` VARCHAR(10) DEFAULT NULL,
	  `Wm` DECIMAL(7,2) DEFAULT NULL
	) ENGINE=INNODB DEFAULT CHARSET=utf8;

    OPEN cur_all;
    REPEAT
        FETCH cur_all INTO v_number, v_city;
        IF NOT _done THEN 
		CALL csdn.pro_flow_modify(v_number,v_city);
        END IF; 
        UNTIL _done=1 END REPEAT;
    CLOSE cur_all; 
    	/*展示下所有的行轉列的資料**/
	SELECT * FROM csdn.flow_tmp;      
END$$   
DELIMITER ;


3,行裡變化儲存過程

通過查詢系統表information_schema.`COLUMNS`來獲取測試表flow_table的所有列,然後寫動態SQL,來把列的值錄入到臨時表flow_tmp中。

DELIMITER $$
DROP PROCEDURE IF EXISTS csdn.`pro_flow_modify`$$
CREATE PROCEDURE csdn.`pro_flow_modify`(p_Number INT,p_city VARCHAR(10))
BEGIN
	DECLARE v_column_name VARCHAR(10) DEFAULT '';
	DECLARE v_exe_sql VARCHAR(1000) DEFAULT '';
	DECLARE v_start_wm VARCHAR(10) DEFAULT '';
	DECLARE v_end_wm VARCHAR(10) DEFAULT '';
	DECLARE v_num  DECIMAL(10,2) DEFAULT 0;
	
	DECLARE i INT DEFAULT 1;
	DECLARE v_Number INT DEFAULT 0;
	SET v_Number=p_Number;
	
	DELETE FROM csdn.flow_n_columns;
	DELETE FROM csdn.flow_tmp WHERE Number=v_Number;
	
	
	/*把測試表flow_table的所有欄位都錄入欄位臨時表中,這樣就達到了從列變成行的目的*/
	INSERT INTO flow_n_columns
	SELECT t.`COLUMN_NAME` FROM information_schema.`COLUMNS` t WHERE t.`TABLE_NAME`='flow_table' AND t.`TABLE_SCHEMA`='csdn' AND t.`COLUMN_NAME` NOT IN('ID','Number','City');
	SELECT column_name INTO v_column_name FROM csdn.flow_n_columns LIMIT 1;
	
	/*開始迴圈遍歷欄位臨時表的欄位資料,並且把欄位值放入臨時表flow_tmp裡面*/
	WHILE i>0 DO
		SET v_exe_sql=CONCAT('INSERT INTO csdn.flow_tmp(Number,City,wm_str,Wm) select ',v_Number,',\'',p_city, '\',\'',v_column_name,'\',',v_column_name,' from csdn.flow_table WHERE flow_table.Number=',v_Number,';');
		SET @sql=v_exe_sql;
		PREPARE s1 FROM @sql;
		EXECUTE s1;
		DEALLOCATE PREPARE s1; 
		DELETE FROM csdn.flow_n_columns WHERE column_name=v_column_name;
		SELECT column_name INTO v_column_name FROM csdn.flow_n_columns LIMIT 1;
		SELECT COUNT(1) INTO i FROM csdn.flow_n_columns ;
		DELETE FROM csdn.flow_tmp WHERE Wm=0;
	END WHILE;

	/*由於觸發器是不支援動態sql,所以不能使用while迴圈,動態遍歷所有統計列的,只能寫死列了,如下所示:
	現在一個個insert只能寫死了, flow_table表有多少個統計列就寫多少個insert sql,以後新新增一個列,就在這裡新新增一條insertsql語句
	INSERT INTO flow_tmp(Number,City,wm_str,Wm) SELECT v_Number,p_city,'wm201403',wm201403 FROM flow_table WHERE Number=v_Number ;
	INSERT INTO flow_tmp(Number,City,wm_str,Wm) SELECT v_Number,p_city,'wm201404',wm201404 FROM flow_table WHERE Number=v_Number ;
	INSERT INTO flow_tmp(Number,City,wm_str,Wm) SELECT v_Number,p_city,'wm201405',wm201405 FROM flow_table WHERE Number=v_Number ;
	INSERT INTO flow_tmp(Number,City,wm_str,Wm) SELECT v_Number,p_city,'wm201406',wm201406 FROM flow_table WHERE Number=v_Number ;
	INSERT INTO flow_tmp(Number,City,wm_str,Wm) SELECT v_Number,p_city,'wm201407',wm201407 FROM flow_table WHERE Number=v_Number ;
	INSERT INTO flow_tmp(Number,City,wm_str,Wm) SELECT v_Number,p_city,'wm201408',wm201408 FROM flow_table WHERE Number=v_Number ;
	*/
	
	/*清除掉不資料=0的列*/
	DELETE FROM csdn.flow_tmp WHERE Wm=0 OR Wm IS NULL;
	
	SELECT wm_str INTO v_start_wm FROM csdn.flow_tmp WHERE Number=v_Number ORDER BY wm_str ASC LIMIT 1;
	SELECT wm_str INTO v_end_wm FROM csdn.flow_tmp WHERE Number=v_Number ORDER BY wm_str DESC LIMIT 1;
	SELECT SUM(Wm) INTO v_num FROM csdn.flow_tmp WHERE Number=v_Number;	
	

    END$$

DELIMITER ;


4,列變行結果展示

臨時表的所有資料:

mysql> SELECT * FROM csdn.flow_tmp;
+--------+----------+----------+--------+
| Number | City     | wm_str   | Wm     |
+--------+----------+----------+--------+
|      1 | shanghai | wm201403 | 100.20 |
|      1 | shanghai | wm201404 | 180.40 |
|      1 | shanghai | wm201405 | 141.00 |
|      1 | shanghai | wm201406 | 164.00 |
|      1 | shanghai | wm201407 | 124.00 |
|      1 | shanghai | wm201408 | 127.00 |
|      2 | shanghai | wm201403 | 110.23 |
|      2 | shanghai | wm201404 | 180.34 |
|      2 | shanghai | wm201405 | 141.23 |
|      2 | shanghai | wm201406 | 104.78 |
|      2 | shanghai | wm201407 | 124.67 |
|      2 | shanghai | wm201408 | 127.45 |
|      3 | beijing  | wm201403 | 123.23 |
|      3 | beijing  | wm201404 | 110.34 |
|      3 | beijing  | wm201405 | 131.33 |
|      3 | beijing  | wm201406 | 154.58 |
|      3 | beijing  | wm201407 | 154.67 |
|      3 | beijing  | wm201408 | 167.45 |
|      4 | hangzhou | wm201404 | 110.34 |
|      4 | hangzhou | wm201405 | 131.33 |
|      4 | hangzhou | wm201406 | 154.58 |
|      4 | hangzhou | wm201407 | 154.67 |
|      5 | hangzhou | wm201405 | 131.33 |
|      5 | hangzhou | wm201406 | 154.58 |
|      5 | hangzhou | wm201407 | 154.67 |
+--------+----------+----------+--------+
25 rows in set (0.00 sec)
mysql>

統計每個使用者的使用總量為:

mysql> SELECT Number,SUM(Wm) 'total_num' FROM flow_tmp GROUP BY Number ORDER BY Number;
+--------+-----------+
| Number | total_num |
+--------+-----------+
|      1 |    836.60 |
|      2 |    788.70 |
|      3 |    841.60 |
|      4 |    550.92 |
|      5 |    440.58 |
+--------+-----------+
5 rows in set (0.00 sec)

mysql>

二,行變列例子演示

1,準備測試資料

USE csdn;
DROP TABLE IF EXISTS csdn.tb;
CREATE TABLE tb(`cname` VARCHAR(10),cource VARCHAR(10),score INT) ENGINE=INNODB;

INSERT INTO tb VALUES('張三','語文',74);
INSERT INTO tb VALUES('張三','數學',83);
INSERT INTO tb VALUES('張三','物理',93);
INSERT INTO tb VALUES('李四','語文',74);
INSERT INTO tb VALUES('李四','數學',84);
INSERT INTO tb VALUES('李四','物理',94);

SELECT * FROM tb;

需要得到的結果是:

+--------------------+--------+--------+--------+-----------+--------------+

| 姓名               | 語文   | 數學   | 物理   | 總成績    | 平均成績     |

+--------------------+--------+--------+--------+-----------+--------------+

| 張三               |  74.00 |  83.00 |  93.00 |    250.00 |        83.33 |

| 李四               |  74.00 |  84.00 |  94.00 |    252.00 |        84.00 |

| 總成績平均數       |  74.00 |  83.50 |  93.50 |    251.00 |        83.67 |

+--------------------+--------+--------+--------+-----------+--------------+

2,利用SUM(IF()) 生成列 + WITH ROLLUP 生成彙總行,並利用 IFNULL將彙總行標題顯示為 Total_num

SQL程式碼塊如下:

SELECT cname AS "姓名",
	SUM(IF(cource="語文",score,0)) AS "語文",
	SUM(IF(cource="數學",score,0)) AS "數學",
	SUM(IF(cource="物理",score,0)) AS "物理",
	SUM(score) AS "總成績",
	ROUND(AVG(score),2) AS "平均成績"
FROM tb 
GROUP BY cname
UNION ALL
SELECT
	"總成績平均數",
	ROUND(AVG(`語文`),2) , ROUND(AVG(`數學`),2), ROUND(AVG(`物理`),2), ROUND(AVG(`總成績`),2), ROUND(AVG(`平均成績`),2)
FROM(
	SELECT "all",cname AS "姓名",
		SUM(IF(cource="語文",score,0)) AS "語文",
		SUM(IF(cource="數學",score,0)) AS "數學",
		SUM(IF(cource="物理",score,0)) AS "物理",
		SUM(score) AS "總成績",
		AVG(score) AS "平均成績"
	FROM tb 
	GROUP BY cname
)tb2 
GROUP BY tb2.all;

執行結果正確,如下所示:

+--------------------+--------+--------+--------+-----------+--------------+

| 姓名               | 語文   | 數學   | 物理   | 總成績    | 平均成績     |

+--------------------+--------+--------+--------+-----------+--------------+

| 張三               |  74.00 |  83.00 |  93.00 |    250.00 |        83.33 |

| 李四               |  74.00 |  84.00 |  94.00 |    252.00 |        84.00 |

| 總成績平均數       |  74.00 |  83.50 |  93.50 |    251.00 |        83.67 |

+--------------------+--------+--------+--------+-----------+--------------+

3,利用max(CASE ... WHEN ... THEN .. ELSE END) AS "語文"的方式來實現

 SQL程式碼如下:

SELECT 
	cname AS "姓名",
	MAX(CASE cource WHEN "語文" THEN score ELSE 0 END) AS "語文", 
	MAX(CASE cource WHEN "數學" THEN score ELSE 0 END) AS "數學", 
	MAX(CASE cource WHEN "物理" THEN score ELSE 0 END) AS "物理", 
	SUM(score) AS "總成績",
	ROUND(AVG(score) ,2) AS "平均成績"
FROM tb 
GROUP BY `cname`
UNION ALL
SELECT
	"總成績平均數",
	ROUND(AVG(`語文`),2) , ROUND(AVG(`數學`),2), ROUND(AVG(`物理`),2), ROUND(AVG(`總成績`),2), ROUND(AVG(`平均成績`),2)
FROM(	SELECT 'all' ,  
		cname AS "姓名",
		MAX(CASE cource WHEN "語文" THEN score ELSE 0 END) AS "語文", 
		MAX(CASE cource WHEN "數學" THEN score ELSE 0 END) AS "數學", 
		MAX(CASE cource WHEN "物理" THEN score ELSE 0 END) AS "物理", 
		SUM(score) AS "總成績",
		ROUND(AVG(score) ,2) AS "平均成績"
	FROM tb 
	GROUP BY `cname` 
)tb2 GROUP BY tb2.all


執行結果正確,如下所示:

+--------------------+--------+--------+--------+-----------+--------------+

| 姓名               | 語文   | 數學   | 物理   | 總成績    | 平均成績     |

+--------------------+--------+--------+--------+-----------+--------------+

| 張三               |  74.00 |  83.00 |  93.00 |    250.00 |        83.33 |

| 李四               |  74.00 |  84.00 |  94.00 |    252.00 |        84.00 |

| 總成績平均數       |  74.00 |  83.50 |  93.50 |    251.00 |        83.67 |

+--------------------+--------+--------+--------+-----------+--------------+

4,利用 WITH rollup結果不符合

SQL程式碼如下:
  SELECT IFNULL(cname,'總平均數') AS "姓名",
	MAX(CASE cource WHEN "語文" THEN score ELSE 0 END) AS "語文", 
	MAX(CASE cource WHEN "數學" THEN score ELSE 0 END) AS "數學", 
	MAX(CASE cource WHEN "物理" THEN score ELSE 0 END) AS "物理", 
	ROUND(AVG(score),2) AS "總成績",
	ROUND(AVG(avg_score),2) AS "平均成績" 
    FROM(
	SELECT   
		cname ,
		IFNULL(cource,'total') cource,
		SUM(score) AS score,
		ROUND(AVG(score) ,2) AS avg_score
	FROM tb 
	GROUP BY `cname`,cource WITH ROLLUP HAVING cname IS NOT NULL
	)tb2 
	GROUP BY  tb2.cname WITH ROLLUP;


執行結果不對,總平均數欄目,裡面各科比較語文數學的班級平均數不對,如下所示:

mysql>     SELECT IFNULL(cname,'總平均數') AS "姓名",
    -> MAX(CASE cource WHEN "語文" THEN score ELSE 0 END) AS "語文", 
    -> MAX(CASE cource WHEN "數學" THEN score ELSE 0 END) AS "數學", 
    -> MAX(CASE cource WHEN "物理" THEN score ELSE 0 END) AS "物理", 
    -> ROUND(AVG(score),2) AS "總成績",
    -> ROUND(AVG(avg_score),2) AS "平均成績" 
    ->     FROM(
    -> SELECT   
    -> 
Display ALL 793 possibilities? (Y OR n) 
    -> cname ,
    -> 
Display ALL 793 possibilities? (Y OR n) 
    -> IFNULL(cource,'total') cource,
    -> 
Display ALL 793 possibilities? (Y OR n) 
    -> SUM(score) AS score,
    -> 
Display ALL 793 possibilities? (Y OR n) 
    -> ROUND(AVG(score) ,2) AS avg_score
    -> FROM tb 
    -> GROUP BY `cname`,cource WITH ROLLUP HAVING cname IS NOT NULL
    -> )tb2 
    -> GROUP BY  tb2.cname WITH ROLLUP;
+--------------+--------+--------+--------+-----------+--------------+
| 姓名         | 語文   | 數學   | 物理   | 總成績    | 平均成績     |
+--------------+--------+--------+--------+-----------+--------------+
| 張三         |     74 |     83 |     93 |    125.00 |        83.33 |
| 李四         |     74 |     84 |     94 |    126.00 |        84.00 |
| 總平均數     |     74 |     84 |     94 |    125.50 |        83.67 |
+--------------+--------+--------+--------+-----------+--------------+
3 ROWS IN SET, 1 warning (0.00 sec)

mysql> 

總結: WITH rollup中對求列的總數是OK的,但是求列的平均數有偏差,這裡場景使用不是恰當。

5,使用動態SQL來實現

SQL程式碼塊如下:

/*僅僅班級成員部分*/
SET @a=''; 
SELECT @a:=CONCAT(@a,'SUM(IF(cource=\'',cource,'\'',',score,0)) AS ',cource,',') FROM (SELECT DISTINCT cource FROM tb) A;
SET @a=CONCAT(@a,"ROUND(AVG(score) ,2) AS \"平均成績\"");
SET @b=CONCAT('SELECT IFNULL(cname,\'總成績\'),',LEFT(@a,LENGTH(@a)-1),' ,SUM(score) AS \"總成績\" FROM tb GROUP BY cname ');

/*班級成員總計部分**/
SET @a2="";
SET @b2=CONCAT('SELECT "all",IFNULL(cname,\'總成績\'),',LEFT(@a,LENGTH(@a)-1),' ,SUM(score) AS \"總成績\" FROM tb GROUP BY cname ');
SELECT @a2:=CONCAT(@a2,'ROUND(AVG(`',cource,'`),2),') FROM (SELECT DISTINCT cource FROM tb) A;
SET @a2=CONCAT(@a2," ROUND(AVG(`平均成績`),2),ROUND(AVG(`總成績`),2) ");
SET @c=CONCAT("SELECT \"班級平均數\",",LEFT(@a2,LENGTH(@a)-1)," FROM(",@b2,")tb2 GROUP BY tb2.all;");
SET @d=CONCAT(@b," UNION ALL ",@c);

PREPARE stmt1 FROM @d;
EXECUTE stmt1;

檢視執行結果如下,已經達到效果:

mysql> /*僅僅班級成員部分*/
mysql> SET @a=''; 
QUERY OK, 0 ROWS affected (0.00 sec)

mysql> SELECT @a:=CONCAT(@a,'SUM(IF(cource=\'',cource,'\'',',score,0)) AS ',cource,',') FROM (SELECT DISTINCT cource FROM tb) A;
+-----------------------------------------------------------------------------------------------------------------------------------+
| @a:=CONCAT(@a,'SUM(IF(cource=\'',cource,'\'',',score,0)) AS ',cource,',')                                                         |
+-----------------------------------------------------------------------------------------------------------------------------------+
| SUM(IF(cource='語文',score,0)) AS 語文,                                                                                           |
| SUM(IF(cource='語文',score,0)) AS 語文,SUM(IF(cource='數學',score,0)) AS 數學,                                                    |
| SUM(IF(cource='語文',score,0)) AS 語文,SUM(IF(cource='數學',score,0)) AS 數學,SUM(IF(cource='物理',score,0)) AS 物理,             |
+-----------------------------------------------------------------------------------------------------------------------------------+
3 ROWS IN SET (0.00 sec)

mysql> SET @a=CONCAT(@a,"ROUND(AVG(score) ,2) AS \"平均成績\"");
QUERY OK, 0 ROWS affected (0.00 sec)

mysql> SET @b=CONCAT('SELECT IFNULL(cname,\'總成績\'),',LEFT(@a,LENGTH(@a)-1),' ,SUM(score) AS \"總成績\" FROM tb GROUP BY cname ');
QUERY OK, 0 ROWS affected (0.00 sec)

mysql> 
mysql> /*班級成員總計部分**/
mysql> SET @a2="";
QUERY OK, 0 ROWS affected (0.00 sec)

mysql> SET @b2=CONCAT('SELECT "all",IFNULL(cname,\'總成績\'),',LEFT(@a,LENGTH(@a)-1),' ,SUM(score) AS \"總成績\" FROM tb GROUP BY cname ');
QUERY OK, 0 ROWS affected (0.00 sec)

mysql> SELECT @a2:=CONCAT(@a2,'ROUND(AVG(`',cource,'`),2),') FROM (SELECT DISTINCT cource FROM tb) A;
+-----------------------------------------------------------------------+
| @a2:=CONCAT(@a2,'ROUND(AVG(`',cource,'`),2),')                        |
+-----------------------------------------------------------------------+
| ROUND(AVG(`語文`),2),                                                 |
| ROUND(AVG(`語文`),2),ROUND(AVG(`數學`),2),                            |
| ROUND(AVG(`語文`),2),ROUND(AVG(`數學`),2),ROUND(AVG(`物理`),2),       |
+-----------------------------------------------------------------------+
3 ROWS IN SET (0.00 sec)

mysql> SET @a2=CONCAT(@a2," ROUND(AVG(`平均成績`),2),ROUND(AVG(`總成績`),2) ");
QUERY OK, 0 ROWS affected (0.00 sec)

mysql> SET @c=CONCAT("SELECT \"班級平均數\",",LEFT(@a2,LENGTH(@a)-1)," FROM(",@b2,")tb2 GROUP BY tb2.all;");
QUERY OK, 0 ROWS affected (0.00 sec)

mysql> SET @d=CONCAT(@b," UNION ALL ",@c);
QUERY OK, 0 ROWS affected (0.00 sec)

mysql> 
mysql> PREPARE stmt1 FROM @d;
QUERY OK, 0 ROWS affected (0.00 sec)
Statement prepared

mysql> EXECUTE stmt1;
+---------------------------+--------+--------+--------+--------------+-----------+
| IFNULL(cname,'總成績')    | 語文   | 數學   | 物理   | 平均成績     | 總成績    |
+---------------------------+--------+--------+--------+--------------+-----------+
| 張三                      |  74.00 |  83.00 |  93.00 |        83.33 |    250.00 |
| 李四                      |  74.00 |  84.00 |  94.00 |        84.00 |    252.00 |
| 班級平均數                |  74.00 |  83.50 |  93.50 |        83.67 |    251.00 |
+---------------------------+--------+--------+--------+--------------+-----------+
3 ROWS IN SET (0.00 sec)

mysql>



相關推薦

MySQL 行列轉換變化各種方法實現總結報表統計 資料記錄統計

                前言:mysql行列變化,最難的就是將多個列變成多行,使用的比較多的是統計學中行變列,列變行,沒有找到現成的函式或者語句,所以自己寫了儲存過程,使用動態sql來實現,應用業務場景,使用者每個月都有使用記錄數錄入一張表,一個月一個欄位,所以表的欄位是動態增長的,現在需要實時統計當

[MySQL] 行列轉換變化各種方法實現總結報表統計資料記錄統計

前言:mysql行列變化,最難的就是將多個列變成多行,使用的比較多的是統計學中行變列,列變行,沒有找到現成的函式或者語句,所以自己寫了儲存過程,使用動態sql來實現,應用業務場景,使用者每個月都有使用記錄數錄入一張表,一個月一個欄位,所以表的欄位是動態增長的,現在需要實時統計

[MySQL] 行列轉換變化各種方法實現總結報表統計資料記錄統計

前言: mysql行列變化,最難的就是將多個列變成多行,使用的比較多的是統計學中行變列,列變行,沒有找到現成的函式或者語句,所以自己寫了儲存過程,使用動態sql來實現,應用業務場景,使用者每個月都有使用記錄數錄入一張表,一個月一個欄位,所以表的欄位是動態增長的,

Mysql 行列轉換

lec gin name select mysql post with clas price 1、創建表CREATE TABLE `gas` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `oil` VARCHAR(100) N

SQL行列轉換6種方法

ati cin 列名 ada ott 計劃 ase mit all 在進行報表開發時,很多時候會遇到行列轉換操作,很對開發人員針對於SQL級別行列轉換操作一直不甚理解,今天正好抽空對其進行了一些簡單的總結。這裏主要列舉3種可以實現SQL行列轉換的方法,包括通用SQL解法以及

前端面試中的各種方法實現

最近在面試,面試官動不動就讓寫一個原生方法的實現,那咱們就在這裡寫一下常見的一些實現: 1.bind Function.prototype.bind2 = function (context) { var self = this; return fu

關於HsahMap的各種方法使用總結

1,map是與collection同級的介面,我們常用它的HashMap實現類HashMap是通過鍵值對應的關係來儲存資訊的,與我們之前的list和set都不一樣每一個key都對應一個value,可以儲存不同的物件我們獲取它儲存的value就只能通過get(key)方法來獲取

動態mysql行列轉換

一,列變成行例子演示1,準備測試資料USE csdn; DROP TABLE IF EXISTS flow_table; CREATE TABLE `flow_table` ( `ID` INT(11) NOT NULL AUTO_INCREMENT, `Number

mysql行列轉換示例

現把轉換方法列舉如下: 1、縱錶轉橫表:     縱表結構 TableA  Name Course Grade 張三 語文 75 張三 數學 80 張三 英語 90 李四 語文 95 李四 數學

資料結構與演算法2——各種方法實現楊輝三角

分別用二維陣列、一維陣列、遞迴等三種方法實現楊輝三角; 楊輝三角:首尾都為1,中間數值等於其肩上兩個數值之和,形如下面: 1

String 常用方法最優演算法實現總結 -- findCommonSubstring 和difference

1. String difference(final String str1, final String str2) 說明:Compares two Strings, and returns the portion where they differ. i.e: ("ahc

mybatis collection 多條件查詢 結合mysql行列轉換

需求:查詢訂單列表,一個訂單 包括訂單號,訂單id.,訂單下的商品列表...等等,訂單的商品列表為N個商品,每個商品包括商品的 id ,名稱,金額,兩個繳費類(商品原因,分為兩種費用,資料庫欄位同一個,繳費型別不同 1,2,所以每個商品其實也是一個兩條記錄的列表,但需求為 兩

String 經常用法最優算法實現總結

lean ... itl min empty turn system then 實現 1. String getOrderedString(boolean isDuplicated, String … str) 說明: Orders all characters in

C#中WinForm程序退出方法技巧總結

ren sender body 登錄 ble 按鈕 動作 打開 alt 一、關閉窗體 在c#中退出WinForm程序包括有很多方法,如:this.Close(); Application.Exit();Application.ExitThread(); System.E

C#中WinForm程序退出方法技巧總結

sys 返回 展開 退出程序 結束 所有 body rgs cat 本文實例總結了C#中WinForm程序退出方法技巧。分享給大家供大家參考。具體分析如下: 在c#中退出WinForm程序包括有很多方法,如:this.Close(); Application.Exit();

java+selenium的使用方法歸納總結持續更新中

selenium的使用 第一步:獲取selenium的jar包及驅動瀏覽器的驅動 在獲取selenium的jar包和瀏覽器的驅動包時,要對照她們的版本號 通過下面可檢視谷歌的版本對應 java+selenium的入門 案例 selenium包 谷歌驅動包 火狐驅動包 IE驅動包

遞迴方法實現深度克隆原理:遍歷物件陣列直到裡邊都是基本資料型別,然後再去複製,就是深度拷貝。

手寫遞迴方法 //定義檢測資料型別的功能函式 function checkedType(target) { return Object.prototype.toString.call(target).slice(8, -1) } //實現深度克隆---物件/陣列 function clon

【TensorFlow】優化方法optimizer總結SGD,Adagrad,Adadelta,Adam,Adamax,Nadam解析十三

本文僅對一些常見的優化方法進行直觀介紹和簡單的比較,主要是一階的梯度法,包括SGD, Momentum, Nesterov Momentum, AdaGrad, RMSProp, Adam。 其中SGD,Momentum,Nesterov Momentum是手動

Java程式碼常用功能實現總結

文章目錄 1.如何取得map裡key得最大值: 2.多執行緒寫法樣例: 1.如何取得map裡key得最大值: 方法一: 將Map中的k

關鍵詞提取方法學習總結TF-IDFTopic-modelRAKE

關鍵詞是一篇文件中表達的主要話題,處理文件或句子時,提取關鍵詞是最重要的工作之一,這在NLP中也是一個十分有用的task。 常見的關鍵詞提取方法有:TF-IDF關鍵詞提取方法、Topic-model關鍵詞提取方法和RAKE關鍵詞提取。 TF-IDF: 使用TF-IDF提取