搞定mysql的 行转列(7种方法) 和 列转行

打印 上一主题 下一主题

主题 861|帖子 861|积分 2587

一、行转列
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()
二、列转行
————————————————
一、行转列

即将本来同一列下多行的不同内容作为多个字段,输出对应内容。
建表语句
  1. DROP TABLE IF EXISTS tb_score;
  2. CREATE TABLE tb_score(
  3.     id INT(11) NOT NULL auto_increment,
  4.     userid VARCHAR(20) NOT NULL COMMENT '用户id',
  5.     subject VARCHAR(20) COMMENT '科目',
  6.     score DOUBLE COMMENT '成绩',
  7.     PRIMARY KEY(id)
  8. )ENGINE = INNODB DEFAULT CHARSET = utf8;
复制代码
插入数据
  1. INSERT INTO tb_score(userid,subject,score) VALUES ('001','语文',90);
  2. INSERT INTO tb_score(userid,subject,score) VALUES ('001','数学',92);
  3. INSERT INTO tb_score(userid,subject,score) VALUES ('001','英语',80);
  4. INSERT INTO tb_score(userid,subject,score) VALUES ('002','语文',88);
  5. INSERT INTO tb_score(userid,subject,score) VALUES ('002','数学',90);
  6. INSERT INTO tb_score(userid,subject,score) VALUES ('002','英语',75.5);
  7. INSERT INTO tb_score(userid,subject,score) VALUES ('003','语文',70);
  8. INSERT INTO tb_score(userid,subject,score) VALUES ('003','数学',85);
  9. INSERT INTO tb_score(userid,subject,score) VALUES ('003','英语',90);
  10. INSERT INTO tb_score(userid,subject,score) VALUES ('003','政治',82);
复制代码
查询数据表中的内容(即转换前的结果)
  1. SELECT * FROM tb_score
复制代码

先来看一下转换后的结果:

可以看出,这里行转列是将原来的subject字段的多行内容选出来,作为结果会集的不同列,并根据userid进行分组表现对应的score。
1、使用case…when…then 进行行转列

  1. SELECT userid,
  2. SUM(CASE `subject` WHEN '语文' THEN score ELSE 0 END) as '语文',
  3. SUM(CASE `subject` WHEN '数学' THEN score ELSE 0 END) as '数学',
  4. SUM(CASE `subject` WHEN '英语' THEN score ELSE 0 END) as '英语',
  5. SUM(CASE `subject` WHEN '政治' THEN score ELSE 0 END) as '政治'
  6. FROM tb_score
  7. GROUP BY userid
复制代码
2、使用IF() 进行行转列:

  1. SELECT userid,
  2. SUM(IF(`subject`='语文',score,0)) as '语文',
  3. SUM(IF(`subject`='数学',score,0)) as '数学',
  4. SUM(IF(`subject`='英语',score,0)) as '英语',
  5. SUM(IF(`subject`='政治',score,0)) as '政治'
  6. FROM tb_score
  7. 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

  1. SELECT IFNULL(userid,'total') AS userid,
  2. SUM(IF(`subject`='语文',score,0)) AS 语文,
  3. SUM(IF(`subject`='数学',score,0)) AS 数学,
  4. SUM(IF(`subject`='英语',score,0)) AS 英语,
  5. SUM(IF(`subject`='政治',score,0)) AS 政治,
  6. SUM(IF(`subject`='total',score,0)) AS total
  7. FROM(
  8.     SELECT userid,IFNULL(`subject`,'total') AS `subject`,SUM(score) AS score
  9.     FROM tb_score
  10.     GROUP BY userid,`subject`
  11.     WITH ROLLUP
  12.     HAVING userid IS NOT NULL
  13. )AS A
  14. GROUP BY userid
  15. WITH ROLLUP;
复制代码
运行结果:

4、利用SUM(IF()) 天生列 + UNION 天生汇总行,并利用 IFNULL将汇总行标题表现为 Total

  1. SELECT userid,
  2. SUM(IF(`subject`='语文',score,0)) AS 语文,
  3. SUM(IF(`subject`='数学',score,0)) AS 数学,
  4. SUM(IF(`subject`='英语',score,0)) AS 英语,
  5. SUM(IF(`subject`='政治',score,0)) AS 政治,
  6. SUM(score) AS TOTAL
  7. FROM tb_score
  8. GROUP BY userid
  9. UNION
  10. SELECT 'TOTAL',SUM(IF(`subject`='语文',score,0)) AS 语文,
  11. SUM(IF(`subject`='数学',score,0)) AS 数学,
  12. SUM(IF(`subject`='英语',score,0)) AS 英语,
  13. SUM(IF(`subject`='政治',score,0)) AS 政治,
  14. SUM(score) FROM tb_score
复制代码
运行结果:

5、利用SUM(IF()) 天生列,直接天生结果不再利用子查询

  1. SELECT IFNULL(userid,'TOTAL') AS userid,
  2. SUM(IF(`subject`='语文',score,0)) AS 语文,
  3. SUM(IF(`subject`='数学',score,0)) AS 数学,
  4. SUM(IF(`subject`='英语',score,0)) AS 英语,
  5. SUM(IF(`subject`='政治',score,0)) AS 政治,
  6. SUM(score) AS TOTAL
  7. FROM tb_score
  8. GROUP BY userid WITH ROLLUP;
复制代码
运行结果:

6、动态,实用于列不确定环境

  1. SET @EE='';
  2. select @EE :=CONCAT(@EE,'sum(if(subject= \'',subject,'\',score,0)) as ',subject, ',') AS aa FROM (SELECT DISTINCT subject FROM tb_score) A ;
  3. SET @QQ = CONCAT('select ifnull(userid,\'TOTAL\')as userid,',@EE,' sum(score) as TOTAL from tb_score group by userid WITH ROLLUP');
  4. -- SELECT @QQ;
  5. PREPARE stmt FROM @QQ;
  6. EXECUTE stmt;
  7. DEALLOCATE PREPARE stmt;
复制代码
运行结果:


7、合并字段表现:利用group_concat()

  1. SELECT userid,GROUP_CONCAT(`subject`,":",score)AS 成绩 FROM tb_score
  2. GROUP BY userid
复制代码
运行结果:

group_concat(),手册上说明:该函数返回带有来自一个组的连接的非NULL值的字符串结果。
比力抽象,难以明确。通俗点明确,其实是如许的:group_concat()会盘算哪些行属于同一组,将属于同一组的列表现出来。要返回哪些列,由函数参数(就是字段名)决定。分组必须有个标准,就是根据group by指定的列进行分组。
结论:group_concat()函数可以很好的建属于同一分组的多个行转化为一个列。
二、列转行

建表语句:
  1. CREATE TABLE tb_score1(
  2.     id INT(11) NOT NULL auto_increment,
  3.     userid VARCHAR(20) NOT NULL COMMENT '用户id',
  4.     cn_score DOUBLE COMMENT '语文成绩',
  5.     math_score DOUBLE COMMENT '数学成绩',
  6.     en_score DOUBLE COMMENT '英语成绩',
  7.     po_score DOUBLE COMMENT '政治成绩',
  8.     PRIMARY KEY(id)
  9. )ENGINE = INNODB DEFAULT CHARSET = utf8;
复制代码
插入数据:
  1. INSERT INTO tb_score1(userid,cn_score,math_score,en_score,po_score) VALUES ('001',90,92,80,0);
  2. INSERT INTO tb_score1(userid,cn_score,math_score,en_score,po_score) VALUES ('002',88,90,75.5,0);
  3. INSERT INTO tb_score1(userid,cn_score,math_score,en_score,po_score) VALUES ('003',70,85,90,82);
复制代码
查询数据表中的内容(即转换前的结果)
  1. SELECT * FROM tb_score1
复制代码

转换后:

本质是将userid的每个科目分数分散成一条记录表现出来。
直接上SQL:
  1. SELECT userid,'语文' AS course,cn_score AS score FROM tb_score1
  2. UNION ALL
  3. SELECT userid,'数学' AS course,math_score AS score FROM tb_score1
  4. UNION ALL
  5. SELECT userid,'英语' AS course,en_score AS score FROM tb_score1
  6. UNION ALL
  7. SELECT userid,'政治' AS course,po_score AS score FROM tb_score1
  8. ORDER BY userid
复制代码
这里将每个userid对应的多个科目的结果查出来,通过UNION ALL将结果集加起来,达到上图的结果。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

王國慶

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表