Mysql中行轉列和列轉行

一、行轉列

即將原本同一列下多行的不同內容作為多個字段,輸出對應內容。

建表語句

DROP TABLE IF EXISTS tb_score;
?
CREATE TABLE tb_score(
??? id INT(11) NOT NULL auto_increment,
??? userid VARCHAR(20) NOT NULL COMMENT '用戶id',
??? subject VARCHAR(20) COMMENT '科目',
??? score DOUBLE COMMENT '成績',
??? PRIMARY KEY(id)
)ENGINE = INNODB DEFAULT CHARSET = utf8;
插入數據

INSERT INTO tb_score(userid,subject,score) VALUES ('001','語文',90);
INSERT INTO tb_score(userid,subject,score) VALUES ('001','數學',92);
INSERT INTO tb_score(userid,subject,score) VALUES ('001','英語',80);
INSERT INTO tb_score(userid,subject,score) VALUES ('002','語文',88);
INSERT INTO tb_score(userid,subject,score) VALUES ('002','數學',90);
INSERT INTO tb_score(userid,subject,score) VALUES ('002','英語',75.5);
INSERT INTO tb_score(userid,subject,score) VALUES ('003','語文',70);
INSERT INTO tb_score(userid,subject,score) VALUES ('003','數學',85);
INSERT INTO tb_score(userid,subject,score) VALUES ('003','英語',90);
INSERT INTO tb_score(userid,subject,score) VALUES ('003','政治',82);
查詢數據表中的內容(即轉換前的結果)

SELECT * FROM tb_score


先來看一下轉換后的結果:



可以看出,這里行轉列是將原來的subject字段的多行內容選出來,作為結果集中的不同列,并根據userid進行分組顯示對應的score。

1、使用case...when....then 進行行轉列

SELECT userid,
SUM(CASE `subject` WHEN '語文' THEN score ELSE 0 END) as '語文',
SUM(CASE `subject` WHEN '數學' THEN score ELSE 0 END) as '數學',
SUM(CASE `subject` WHEN '英語' THEN score ELSE 0 END) as '英語',
SUM(CASE `subject` WHEN '政治' THEN score ELSE 0 END) as '政治'
FROM tb_score
GROUP BY userid
2、使用IF() 進行行轉列:

SELECT userid,
SUM(IF(`subject`='語文',score,0)) as '語文',
SUM(IF(`subject`='數學',score,0)) as '數學',
SUM(IF(`subject`='英語',score,0)) as '英語',
SUM(IF(`subject`='政治',score,0)) as '政治'
FROM tb_score
GROUP BY userid
注意點:

(1)SUM() 是為了能夠使用GROUP BY根據userid進行分組,因為每一個userid對應的subject="語文"的記錄只有一條,所以SUM() 的值就等于對應那一條記錄的score的值。

假如userid ='001' and subject='語文' 的記錄有兩條,則此時SUM() 的值將會是這兩條記錄的和,同理,使用Max()的值將會是這兩條記錄里面值最大的一個。但是正常情況下,一個user對應一個subject只有一個分數,因此可以使用SUM()、MAX()、MIN()、AVG()等聚合函數都可以達到行轉列的效果。

(2)IF(subject='語文',score,0) 作為條件,即對所有subject='語文'的記錄的score字段進行SUM()、MAX()、MIN()、AVG()操作,如果score沒有值則默認為0。

3、利用SUM(IF()) 生成列 + WITH ROLLUP 生成匯總行,并利用 IFNULL將匯總行標題顯示為Total

SELECT IFNULL(userid,'total') AS userid,
SUM(IF(`subject`='語文',score,0)) AS 語文,
SUM(IF(`subject`='數學',score,0)) AS 數學,
SUM(IF(`subject`='英語',score,0)) AS 英語,
SUM(IF(`subject`='政治',score,0)) AS 政治,
SUM(IF(`subject`='total',score,0)) AS total
FROM(
??? SELECT userid,IFNULL(`subject`,'total') AS `subject`,SUM(score) AS score
??? FROM tb_score
??? GROUP BY userid,`subject`
??? WITH ROLLUP
??? HAVING userid IS NOT NULL
)AS A
GROUP BY userid
WITH ROLLUP;
運行結果:



4、利用SUM(IF()) 生成列 + UNION 生成匯總行,并利用 IFNULL將匯總行標題顯示為 Total

SELECT userid,
SUM(IF(`subject`='語文',score,0)) AS 語文,
SUM(IF(`subject`='數學',score,0)) AS 數學,
SUM(IF(`subject`='英語',score,0)) AS 英語,
SUM(IF(`subject`='政治',score,0)) AS 政治,
SUM(score) AS TOTAL
FROM tb_score
GROUP BY userid
UNION
SELECT 'TOTAL',SUM(IF(`subject`='語文',score,0)) AS 語文,
SUM(IF(`subject`='數學',score,0)) AS 數學,
SUM(IF(`subject`='英語',score,0)) AS 英語,
SUM(IF(`subject`='政治',score,0)) AS 政治,
SUM(score) FROM tb_score
運行結果:



5、利用SUM(IF()) 生成列,直接生成結果不再利用子查詢

SELECT IFNULL(userid,'TOTAL') AS userid,
SUM(IF(`subject`='語文',score,0)) AS 語文,
SUM(IF(`subject`='數學',score,0)) AS 數學,
SUM(IF(`subject`='英語',score,0)) AS 英語,
SUM(IF(`subject`='政治',score,0)) AS 政治,
SUM(score) AS TOTAL
FROM tb_score
GROUP BY userid WITH ROLLUP;
運行結果:



6、動態,適用于列不確定情況

SET @EE='';
select @EE :=CONCAT(@EE,'sum(if(subject= \'',subject,'\',score,0)) as ',subject, ',') AS aa FROM (SELECT DISTINCT subject FROM tb_score) A ;
?
SET @QQ = CONCAT('select ifnull(userid,\'TOTAL\')as userid,',@EE,' sum(score) as TOTAL from tb_score group by userid WITH ROLLUP');
-- SELECT @QQ;
?
PREPARE stmt FROM @QQ;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
運行結果:





7、合并字段顯示:利用group_concat()

SELECT userid,GROUP_CONCAT(`subject`,":",score)AS 成績 FROM tb_score
GROUP BY userid
運行結果:



group_concat(),手冊上說明:該函數返回帶有來自一個組的連接的非NULL值的字符串結果。
比較抽象,難以理解。通俗點理解,其實是這樣的:group_concat()會計算哪些行屬于同一組,將屬于同一組的列顯示出來。要返回哪些列,由函數參數(就是字段名)決定。分組必須有個標準,就是根據group by指定的列進行分組。

結論:groupconcat()函數可以很好的建屬于同一分組的多個行轉化為一個列。

三、列轉行

建表語句:

CREATE TABLE tb_score1(
??? id INT(11) NOT NULL auto_increment,
??? userid VARCHAR(20) NOT NULL COMMENT '用戶id',
??? cn_score DOUBLE COMMENT '語文成績',
??? math_score DOUBLE COMMENT '數學成績',
??? en_score DOUBLE COMMENT '英語成績',
??? po_score DOUBLE COMMENT '政治成績',
??? PRIMARY KEY(id)
)ENGINE = INNODB DEFAULT CHARSET = utf8;
插入數據:

INSERT INTO tb_score1(userid,cn_score,math_score,en_score,po_score) VALUES ('001',90,92,80,0);
INSERT INTO tb_score1(userid,cn_score,math_score,en_score,po_score) VALUES ('002',88,90,75.5,0);
INSERT INTO tb_score1(userid,cn_score,math_score,en_score,po_score) VALUES ('003',70,85,90,82);
查詢數據表中的內容(即轉換前的結果)

SELECT * FROM tb_score1

轉換后:

本質是將userid的每個科目分數分散成一條記錄顯示出來。

直接上SQL:

SELECT userid,'語文' AS course,cn_score AS score FROM tb_score1
UNION ALL
SELECT userid,'數學' AS course,math_score AS score FROM tb_score1
UNION ALL
SELECT userid,'英語' AS course,en_score AS score FROM tb_score1
UNION ALL
SELECT userid,'政治' AS course,po_score AS score FROM tb_score1
ORDER BY userid
這里將每個userid對應的多個科目的成績查出來,通過UNION ALL將結果集加起來,達到上圖的效果。

附:UNION與UNION ALL的區別(摘):

1.對重復結果的處理:UNION會去掉重復記錄,UNION ALL不會;

2.對排序的處理:UNION會排序,UNION ALL只是簡單地將兩個結果集合并;

3.效率方面的區別:因為UNION 會做去重和排序處理,因此效率比UNION ALL慢很多;

轉載于:https://www.cnblogs.com/zhuyeshen/p/10917357.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/393579.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/393579.shtml
英文地址,請注明出處:http://en.pswp.cn/news/393579.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

OSChina 周四亂彈 ——妹子喜歡的是程序員 這是標準……

2019獨角獸企業重金招聘Python工程師標準>>> Osc亂彈歌單(2017)請戳(這里) 【今日歌曲】 一葉孤鴻 :分享Nanaka的單曲《いのちの名前(Cover 木村弓)》 《いのちの名前(C…

阿里薪資談判技巧_如何像專業人士一樣處理技術職業中的薪資談判

阿里薪資談判技巧by Aline Lerner通過艾琳勒納(Aline Lerner) 如何像專業人士一樣處理技術職業中的薪資談判 (How to handle salary negotiations in your tech career like a pro) 確切地談薪水時要說些什么 (Know exactly what to say when negotiating your salary) There …

xp系統sql服務器怎么找,SQL文件在winxp系統下怎么打開

很多用戶不知道SQL文件是什么?SQL文件怎么打開?我們存儲數據時候經常會遇到SQL文件,如果你不知道WinXP系統SQL文件是什么以及怎么打開的話,那就趕緊看看小編整理的以下文章內容吧!SQL文件是什么?學習編程的同學可能都知道SQL是一種高級的非過程化的編…

Silverlight 設計器加載錯誤

每次打開silverlight頁面出如下錯誤 然后設計器不能將頁面加載出來 最后找了蠻多資料的 感覺這個原因有可能:“控制面板的添加刪除程序那里,選中Microsoft Silverlight,看看他的版本,是否與所裝的SDK的版本號一致。就算兩個版本號…

mysql索引優化實際例子_MySQL索引優化的實際案例分析

Order by desc/asc limit M是我在mysql sql優化中經常遇到的一種場景,其優化原理也非常的簡單,就是利用索引的有序性,優化器沿著索引的順序掃描,在掃描到符合條件的M行數據后,停止掃描;看起來非常的簡單&am…

leetcode441. 排列硬幣(二分查找)

你總共有 n 枚硬幣,你需要將它們擺成一個階梯形狀,第 k 行就必須正好有 k 枚硬幣。 給定一個數字 n,找出可形成完整階梯行的總行數。 n 是一個非負整數,并且在32位有符號整型的范圍內。 示例 1: n 5 硬幣可排列成以下幾行: …

【洛谷 P2051】 [AHOI2009]中國象棋(DP)

題目鏈接 首先想到狀壓dp,但是\(n,m\)高達100,怎么壓? 容易發現,每行每列最多兩個象棋,否則就直接gg了。 一個巧妙的設置狀態的方式是,只需要記錄到當前行有多少列是放了1個炮和2個炮。 然后每一行有3種選擇…

循環 直到 python_如果您在Python中存在慢循環,則可以對其進行修復……直到無法解決為止...

循環 直到 pythonby Maxim Mamaev馬克西姆馬馬耶夫(Maxim Mamaev) Let’s take a computational problem as an example, write some code, and see how we can improve the running time. Here we go.讓我們以一個計算問題為例,編寫一些代碼,看看如何改…

阿里云視頻點播解決方案使用教程

2019獨角獸企業重金招聘Python工程師標準>>> 課程介紹 視頻點播(ApsaraVideo for VoD,簡稱VoD)是集視頻音視頻采集、編輯、上傳、自動化轉碼處理、媒體資源管理、分發加速于一體的一站式音視頻點播解決方案。 產品詳情&#xff1a…

云服務器安裝操作系統后如何連接,服務器如何安裝操作系統

服務器如何安裝操作系統 內容精選換一換如果您需要使用畢昇編譯器,則需要先在服務端安裝畢昇編譯器。畢昇編譯器基于開源LLVM開發,并進行了優化和改進,同時將flang作為默認的Fortran語言前端編譯器,是針對鯤鵬平臺的高性能編譯器。…

換行符

非原創windows保留\r\n作為換行符的原因: 回車鍵為什么叫回車鍵,大家有想過沒有,字面意思是回去的車子。 第一臺打印機,每一行打印完了之后在打印第二行之前,這個噴墨的玩意兒需要先回到這一行的行首,這叫回…

leetcode劍指 Offer 53 - II. 0~n-1中缺失的數字(二分查找)

一個長度為n-1的遞增排序數組中的所有數字都是唯一的,并且每個數字都在范圍0~n-1之內。在范圍0~n-1內的n個數字中有且只有一個數字不在該數組中,請找出這個數字。 示例 1: 輸入: [0,1,3] 輸出: 2 代碼 class Solution {public…

python 0基礎起步學習day2

元組:戴上了枷鎖的列表 元組是不可改變的,元組是不能隨意改變內部的元素的 元組和列表很像,它可以看成是不可修改的列表 所以創建元祖逗號是關鍵 因為(8,)是元組,這里*就不再是乘號,而是重復拷貝符【重復操作符】 直接…

react中的狀態機_在基于狀態圖的狀態機上使用React的模式

react中的狀態機by Shawn McKay肖恩麥凱(Shawn McKay) 在基于狀態圖的狀態機上使用React的模式 (Patterns for using React with Statechart-based state machines) Statecharts and state machines offer a promising path for designing and managing complex state in apps…

android scheme打開天貓,淘寶

直接上代碼 Intent intent new Intent(); intent.setAction("android.intent.action.VIEW"); /*String url "taobao://shop.m.taobao.com/shop/shop_index.htm?shop_id131259851&spma230r.7195193.1997079397.8.Pp3ZMM&point" "%7B%22…

leetcode1337. 方陣中戰斗力最弱的 K 行(優先隊列)

給你一個大小為 m * n 的方陣 mat,方陣由若干軍人和平民組成,分別用 1 和 0 表示。 請你返回方陣中戰斗力最弱的 k 行的索引,按從最弱到最強排序。 如果第 i 行的軍人數量少于第 j 行,或者兩行軍人數量相同但 i 小于 j&#xff…

dp 1.4協議_淺析關于HDMI接口與DP接口

顯示器現在主流已經為HDMI接口與DP接口,那么這些接口都有什么區別,以下表格會大致做個區分,建議優先使用DP接口。(HDMI2.1接口目前僅發布協議,尚未大規模商用在高清電視機上有部分應用,Mini DP接口版本為DP…

淺談 JDBC 中 CreateStatement 和 PrepareStatement 的區別與優劣。

淺談 JDBC 中 CreateStatement 和 PrepareStatement 的區別與優劣。

jsp 構建單頁應用_如何使用服務器端Blazor構建單頁應用程序

jsp 構建單頁應用介紹 (Introduction) In this article, we will create a Single Page Application (SPA) using server-side Blazor. We will use an Entity Framework Core database. Single-Page Applications are web applications that load a single HTML page. They dy…

Apache的虛擬主機配置

虛擬主機配置一般可以分為:基于域名基于端口基于IP配置虛擬主機檢查防火墻,端口是否打開apache的配置文件。service iptables status #查看防火墻netstat -anp | grep 8021 #端口是必須要考慮的問題locate httpd.confmkdir -p /usr/local/apache/conf/ex…