目录
一、行转列
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 '成绩',
- PRIMARY KEY (`id`)
- ) 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);
行数据:
列数据:
- SELECT
- userid,
- 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 ) '政治'
- FROM
- tb_score
- GROUP BY
- userid;
- SELECT
- userid,
- SUM( IF ( subjectName = '语文', score, 0 ) ) '语文',
- SUM( IF ( subjectName = '数学', score, 0 ) ) '数学',
- SUM( IF ( subjectName = '英语', score, 0 ) ) '英语',
- SUM( IF ( subjectName = '政治', score, 0 ) ) '政治'
- FROM
- tb_score
- GROUP BY
- userid;
MySQL提供了 group by with rollup 函数进行group by 字段的汇总,但是与order by 互斥的不能同时用。
- SELECT
- 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'
- FROM
- (
- SELECT
- userid,
- IFNULL( subjectName, 'total' ) AS subjectName,
- SUM( score ) AS score
- FROM
- tb_score
- GROUP BY userid, subjectName WITH ROLLUP
- ) AS a
- GROUP BY userid
- WITH ROLLUP;
- 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 '政治',
- SUM(score) AS total
- FROM tb_score
- GROUP BY userid WITH ROLLUP;
- SELECT 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 '政治',
- SUM(score) AS total
- FROM tb_score
- GROUP BY userid
- UNION
- 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;
- 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;
3、4、5、6、执行结果如下:
SELECT userid,GROUP_CONCAT(`subjectName`,':',score)AS 成绩 FROM tb_score GROUP BY userid;
group_concat() 计算哪些行属于同一组,将属于同一组的列显示出来。要返回哪些列,由函数参数(就是字段名)决定。分组 是根据group by指定的列进行分组。
执行结果:
- CREATE TABLE tb_score1(
- 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 '政治成绩',
- PRIMARY KEY(id)
- )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);
- SELECT * FROM tb_score1;
查询结果:
列转行:将每个userid对应的多个科目的成绩查出来,通过UNION ALL将结果集加起来。
- select userId,'语文' as subjectName,chinese_score as score from tb_score1
- union all
- select userId,'数学' as subjectName,math_score as score from tb_score1
- union all
- select userId,'英语' as subjectName,english_score as score from tb_score1
- union all
- select userId,'政治' as subjectName,politics_score as score from tb_score1;
转换后结果:
UNION : 会去掉重复记录,会排序,因为UNION 会做去重和排序处理,效率比UNION ALL慢很多。
UNION ALL :不会对结果进行去重处理,只是简单地将两个结果集合并。
参考文章:
联系客服