目录
一、行转列
1、使用case…when…then
2、使用SUM(IF()) 生成列
3、使用SUM(IF()) 生成列 + WITH ROLLUP 生成汇总行
4、使用SUM(IF()) 生成列,直接生成汇总结果,不再利用子查询
5、使用SUM(IF()) 生成列 + UNION 生成汇总行,并利用 IFNULL将汇总行标题显示为 Total
6、动态查询列值不确定的情况
7、合并字段显示:group_concat()
二、列转行
一、行转列
将原本同一列下多行的不同内容作为多个字段,输出对应内容。
表及数据sql:
CREATE TABLE `tb_score` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userid` varchar(20) NOT NULL COMMENT '用户id', `subjectName` varchar(20) DEFAULT NULL COMMENT '科目', `score` double DEFAULT NULL COMMENT '成绩', ) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8; INSERT INTO `tb_score`(`id`, `userid`, `subjectName`, `score`) VALUES (1, '001', '语文', 90); INSERT INTO `tb_score`(`id`, `userid`, `subjectName`, `score`) VALUES (2, '001', '数学', 92); INSERT INTO `tb_score`(`id`, `userid`, `subjectName`, `score`) VALUES (3, '001', '英语', 80); INSERT INTO `tb_score`(`id`, `userid`, `subjectName`, `score`) VALUES (4, '002', '语文', 88); INSERT INTO `tb_score`(`id`, `userid`, `subjectName`, `score`) VALUES (5, '002', '数学', 90); INSERT INTO `tb_score`(`id`, `userid`, `subjectName`, `score`) VALUES (6, '002', '英语', 75.5); INSERT INTO `tb_score`(`id`, `userid`, `subjectName`, `score`) VALUES (7, '003', '语文', 70); INSERT INTO `tb_score`(`id`, `userid`, `subjectName`, `score`) VALUES (8, '003', '数学', 85); INSERT INTO `tb_score`(`id`, `userid`, `subjectName`, `score`) VALUES (9, '003', '英语', 90); INSERT INTO `tb_score`(`id`, `userid`, `subjectName`, `score`) VALUES (10, '003', '政治', 82); INSERT INTO `tb_score`(`id`, `userid`, `subjectName`, `score`) VALUES (11, '004', '政治', 82); INSERT INTO `tb_score`(`id`, `userid`, `subjectName`, `score`) VALUES (12, '004', '英语', 83);
行数据:
列数据:
1、使用case…when…then
SUM( CASE subjectName WHEN '语文' THEN score ELSE 0 END ) '语文', SUM( CASE subjectName WHEN '数学' THEN score ELSE 0 END ) '数学', SUM( CASE subjectName WHEN '英语' THEN score ELSE 0 END ) '英语', SUM( CASE subjectName WHEN '政治' THEN score ELSE 0 END ) '政治'
2、使用SUM(IF()) 生成列
SUM( IF ( subjectName = '语文', score, 0 ) ) '语文', SUM( IF ( subjectName = '数学', score, 0 ) ) '数学', SUM( IF ( subjectName = '英语', score, 0 ) ) '英语', SUM( IF ( subjectName = '政治', score, 0 ) ) '政治'
3、使用SUM(IF()) 生成列 + WITH ROLLUP 生成汇总行
MySQL提供了 group by with rollup 函数进行group by 字段的汇总,但是与order by 互斥的不能同时用。
IFNULL( userid, 'total' ) AS userid, SUM( IF ( subjectName = '语文', score, 0 ) ) '语文', SUM( IF ( subjectName = '数学', score, 0 ) ) '数学', SUM( IF ( subjectName = '英语', score, 0 ) ) '英语', SUM( IF ( subjectName = '政治', score, 0 ) ) '政治', SUM( IF ( subjectName = 'total', score, 0 ) ) AS 'total' IFNULL( subjectName, 'total' ) AS subjectName, GROUP BY userid, subjectName WITH ROLLUP
4、使用SUM(IF()) 生成列,直接生成汇总结果,不再利用子查询
SELECT IFNULL(userid,'total') AS userid, SUM(IF(subjectName='语文',score,0)) AS '语文', SUM(IF(subjectName='数学',score,0)) AS '数学', SUM(IF(subjectName='英语',score,0)) AS '英语', SUM(IF(subjectName='政治',score,0)) AS '政治', GROUP BY userid WITH ROLLUP;
5、使用SUM(IF()) 生成列 + UNION 生成汇总行,并利用 IFNULL将汇总行标题显示为 Total
SUM(IF(subjectName='语文',score,0)) AS '语文', SUM(IF(subjectName='数学',score,0)) AS '数学', SUM(IF(subjectName='英语',score,0)) AS '英语', SUM(IF(subjectName='政治',score,0)) AS '政治', SELECT 'total',SUM(IF(subjectName='语文',score,0)) AS '语文', SUM(IF(subjectName='数学',score,0)) AS '数学', SUM(IF(subjectName='英语',score,0)) AS '英语', SUM(IF(subjectName='政治',score,0)) AS '政治', SUM(score) FROM tb_score;
6、动态查询列值不确定的情况
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');
3、4、5、6、执行结果如下:
7、合并字段显示:group_concat()
SELECT userid,GROUP_CONCAT(`subjectName`,':',score)AS 成绩 FROM tb_score GROUP BY userid;
group_concat() 计算哪些行属于同一组,将属于同一组的列显示出来。要返回哪些列,由函数参数(就是字段名)决定。分组 是根据group by指定的列进行分组。
执行结果:
二、列转行
id INT(11) NOT NULL auto_increment, userid VARCHAR(20) NOT NULL COMMENT '用户id', chinese_score DOUBLE COMMENT '语文成绩', math_score DOUBLE COMMENT '数学成绩', english_score DOUBLE COMMENT '英语成绩', politics_score DOUBLE COMMENT '政治成绩', )ENGINE = INNODB DEFAULT CHARSET = utf8; INSERT INTO tb_score1(userid,chinese_score,math_score,english_score,politics_score) VALUES ('001',90,92,80,0); INSERT INTO tb_score1(userid,chinese_score,math_score,english_score,politics_score) VALUES ('002',88,90,75.5,0); INSERT INTO tb_score1(userid,chinese_score,math_score,english_score,politics_score) VALUES ('003',70,85,90,82); INSERT INTO tb_score1(userid,chinese_score,math_score,english_score,politics_score) VALUES ('003',0,0,83,82);
查询结果:
列转行:将每个userid对应的多个科目的成绩查出来,通过UNION ALL将结果集加起来。
select userId,'语文' as subjectName,chinese_score as score from tb_score1 select userId,'数学' as subjectName,math_score as score from tb_score1 select userId,'英语' as subjectName,english_score as score from tb_score1 select userId,'政治' as subjectName,politics_score as score from tb_score1;
转换后结果:
UNION : 会去掉重复记录,会排序,因为UNION 会做去重和排序处理,效率比UNION ALL慢很多。
UNION ALL :不会对结果进行去重处理,只是简单地将两个结果集合并。
参考文章:
一篇文章搞定mysql的 行转列(7种方法) 和 列转行
|