<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

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

        來源:懂視網 責編:小采 時間:2020-11-09 19:44:11
        文檔

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

        [MySQL]行列轉換變化各種方法實現總結(行變列報表統計、列變行數據記錄統計等)_MySQL:前言: mysql行列變化,最難的就是將多個列變成多行,使用的比較多的是統計學中行變列,列變行,沒有找到現成的函數或者語句,所以自己寫了存儲過程,使用動態sql來實現,應用業務場景,用戶每個月都有使用記錄數錄入一張表,一個月一個字段,所以表的字段是
        推薦度:
        導讀[MySQL]行列轉換變化各種方法實現總結(行變列報表統計、列變行數據記錄統計等)_MySQL:前言: mysql行列變化,最難的就是將多個列變成多行,使用的比較多的是統計學中行變列,列變行,沒有找到現成的函數或者語句,所以自己寫了存儲過程,使用動態sql來實現,應用業務場景,用戶每個月都有使用記錄數錄入一張表,一個月一個字段,所以表的字段是

        前言:

        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>
        

        參考文章地址:http://blog.chinaunix.net/uid-7692530-id-2567582.html

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

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

        [MySQL]行列轉換變化各種方法實現總結(行變列報表統計、列變行數據記錄統計等)_MySQL:前言: mysql行列變化,最難的就是將多個列變成多行,使用的比較多的是統計學中行變列,列變行,沒有找到現成的函數或者語句,所以自己寫了存儲過程,使用動態sql來實現,應用業務場景,用戶每個月都有使用記錄數錄入一張表,一個月一個字段,所以表的字段是
        推薦度:
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 91视频国产免费| 无人在线直播免费观看| 波多野结衣久久高清免费| 亚洲性色成人av天堂| 免费精品一区二区三区第35| 亚洲精品视频在线观看你懂的| 老司机免费午夜精品视频| 国产jizzjizz免费视频| 老外毛片免费视频播放| 国产av无码专区亚洲国产精品| 成人午夜免费视频| 亚洲午夜精品久久久久久浪潮| 美女被免费视频网站| 伊人久久精品亚洲午夜| 91在线视频免费观看| 亚洲高清无在码在线电影不卡| 黄色网址免费大全| 亚洲熟妇无码av另类vr影视| 国产在线98福利播放视频免费| 国产av无码专区亚洲av毛片搜| www国产亚洲精品久久久日本| 黄色免费在线网址| 亚洲精品高清无码视频| 桃子视频在线观看高清免费视频| 亚洲色欲色欲www| 国产精品另类激情久久久免费 | 久久中文字幕免费视频| 久久综合亚洲色一区二区三区| 成人免费午夜在线观看| 免费人成网站永久| 亚洲伊人tv综合网色| 在线免费视频一区| a毛片全部播放免费视频完整18| 亚洲理论片在线观看| 国产在线观看免费视频播放器| 中文精品人人永久免费| 亚洲冬月枫中文字幕在线看| 国产jizzjizz免费看jizz| 久久久久免费看黄a级试看| 亚洲精品国产精品| 亚洲大片在线观看|