龙空技术网

MySQL的行与列转换

frankdou 714

前言:

现在小伙伴们对“mysqlsql行转列”大概比较看重,朋友们都需要剖析一些“mysqlsql行转列”的相关资讯。那么小编也在网摘上搜集了一些对于“mysqlsql行转列””的相关内容,希望朋友们能喜欢,我们一起来了解一下吧!

MySQL的行转列一、前言之前小伙伴反应在很多面试过程中,经常在数据库方面问到关于行和列的问题,今天真好在做数据展示的时候,发现自己sql语句执行的结果无法满足图标的需求,需要将查询结果多列转多行。二、行转列的方案1、初始的数据1.1 初始化的建表语句

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));
1.2 初始化数据的SQL
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);
2、查询的表的数据2.1 查询数据表中所有的原始内容
SELECT * FROM tb_score
2.2 我们想得到一下图片的结果

以上图片显示结果可以看出,这里行转列是将原来的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
以上两种方式说明:SUM() 是为了能够使用GROUP BY根据userid进行分组,因为每一个userid对应的subject="语文"的记录只有一条,所以SUM() 的值就等于对应那一条记录的score的值。假如userid =‘001’ and subject=‘语文’ 的记录有两条,则此时SUM() 的值将会是这两条记录的和,同理,使用Max()的值将会是这两条记录里面值最大的一个。但是正常情况下,一个user对应一个subject只有一个分数,因此可以使用SUM()、MAX()、MIN()、AVG()等聚合函数都可以达到行转列的效果。IF(subject=‘语文’,score,0) 作为条件,即对所有subject='语文’的记录的score字段进行SUM()、MAX()、MIN()、AVG()操作,如果score没有值则默认为0。3、利用SUM(IF()) 生成列 + WITH [ROLLUP]
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 totalFROM(    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
4、利用SUM(IF()) 生成列 + UNION 生成汇总行
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_scoreGROUP BY useridUNIONSELECT '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_scoreGROUP 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、合并字段显示

SELECT userid,GROUP_CONCAT(`subject`,":",score)AS 成绩 FROM tb_scoreGROUP BY userid
MySQL的列转行1、初始化建表语句
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;
2、初始化数据
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);
3、查询数据表中的内容【没有转换的结果】
SELECT * FROM tb_score1
3.1 转换前的数据结果3.2 转换后的数据结果

这里将每个userid对应的多个科目的成绩查出来,通过UNION ALL将结果集加起来,达到上图的效果。

SELECT userid,'语文' AS course,cn_score AS score FROM tb_score1UNION ALLSELECT userid,'数学' AS course,math_score AS score FROM tb_score1UNION ALLSELECT userid,'英语' AS course,en_score AS score FROM tb_score1UNION ALLSELECT userid,'政治' AS course,po_score AS score FROM tb_score1ORDER BY userid

标签: #mysqlsql行转列