设为首页 收藏本站
查看: 1292|回复: 0

[经验分享] sql行转列、列转行的方法

[复制链接]

尚未签到

发表于 2018-10-20 11:21:48 | 显示全部楼层 |阅读模式
DSC0000.jpg

  如题:有一张表EMP,里面有两个字段:name,chengji  有三条记录,分别表示语文(name) 70分,数学(name) 80分,英语(name) 58分,请用一条sql查询出这三条记录并以条件显示出来,大于等于80表示优秀,大于等于60表示及格,小于60分表示不及格!要求显示格式如上!
  首先我们创建表,添加如题数据!
  CREATE TABLE emp(NAME VARCHAR(20),chengji INT);
  INSERT INTO emp VALUES('语文',70),('数学',80),('英语',58);
DSC0001.png

  根据题目要求,我们需要将这三行的结果做判断,然后以列的形式显示,这其中有一个行转列的操作。
  第一种sql写法:
  SELECT MAX(CASE WHEN  NAME='语文' THEN (CASE WHEN chengji>=80  THEN '优秀' WHEN   chengji=60 THEN '及格' ELSE  '不及格' END)  ELSE '' END) '语文'  ,
  MAX(CASE WHEN  NAME='数学' THEN (CASE WHEN chengji>=80  THEN '优秀' WHEN   chengji=60 THEN '及格' ELSE  '不及格' END)  ELSE '' END)  '数学',
  MAX(CASE WHEN  NAME='英语' THEN (CASE WHEN chengji>=80  THEN '优秀' WHEN   chengji=60 THEN '及格' ELSE  '不及格' END) ELSE '' END ) '英语' FROM  emp
  执行结果如下:
DSC0002.png

  备注:上述sql中使用了max(case)这种用法,max这里的主要作用是为了在3次判断中,取到不为空字符串''的标题,语文,数学,英语!
  第二种写法采用group_concat函数也是可以拼接出如图所有要的结果写法如下:
  SELECT GROUP_CONCAT(NAME SEPARATOR '|')  FROM   emp  UNION ALL   SELECT
  GROUP_CONCAT(CASE WHEN chengji>=80  THEN '优秀' WHEN   chengji=60 THEN '及格' ELSE  '不及格' END   SEPARATOR '|' ) FROM  emp
  执行结果如下:
DSC0003.png

  这样看,这个结果也还是可以接受, 这里采用了group_concat函数,将列的类容连接起来,作为行!不过这样的结果有点生硬的感觉!
  补充一点:这里的sql写法我们可以看出,如果想要通过第一种写法。我们前面必须要知道列的内容如语文,数学,英语,但是第二种我们却不用知道! 这里我们想到了一种方法,通过存储过程,将想要的第一种方法的sql拼出来,然后执行这样的话,后面如果我们的表再添加列,或者减少列,也不会报错!
  写法如下:
  DELIMITER $$
  USE `yhtest`$$
  DROP PROCEDURE IF EXISTS `yhtest`$$
  CREATE DEFINER=`root`@`%` PROCEDURE `yhtest`()
  BEGIN
  SET @sql = NULL;
  SELECT
  GROUP_CONCAT(DISTINCT
  CONCAT(
  'MAX(CASE WHEN  NAME=','\'',emp.name,'\'','THEN (CASE WHEN chengji>=80  THEN ', '\'' ,'优秀','\'' ,' WHEN
  chengji=60 THEN ', '\'' ,'及格' ,'\'' ,' ELSE ', '\'' ,'不及格' ,'\'' ,' END)  ELSE ', '\'','\'',' END) ','\'',emp.name,'\''
  )
  )
  INTO @sql
  FROM emp ;
  SET @sql = CONCAT('select  ',@sql, ' from  emp');
  PREPARE stmt1 FROM @sql;
  EXECUTE stmt1;
  DEALLOCATE PREPARE stmt1;
  END$$
  DELIMITER ;
  调用一下: call yhtest();
DSC0004.png

  插入几条数据!我们假设提前不知道有多少个科目!
  INSERT INTO emp VALUES('物理',72),('体育',84);
DSC0005.png

  这里有个问题!由于我们在存储过程中使用了group_concat函数,这个拼接函数最大拼接长度为1024(默认) 超过固定长度,截断处理! 由数据库参数group_concat_max_len 控制!我们可以根据需要认为调整!
  group_concat  调整拼接符号 :group_concat(name  separator  '_')
  group_concat  排序:group_concat(name order by name  separator  '_')


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-624007-1-1.html 上篇帖子: socket 之非阻塞 Server 下篇帖子: sql语句条件里between的用法
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

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