lotus

贵有恒何必三更眠五更起 最无益只怕一日曝十日寒

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
  1846 随笔 :: 0 文章 :: 109 评论 :: 288万 阅读

https://blog.csdn.net/nanyangnongye/article/details/125217634

 

版本说明

mysql8.0

😍 一、行转列
🍀需求


🚩 经典case when实现
select

name,

max(case subject when '语文' then resuilt else 0 end) '语文',

max(case subject when '数学' then resuilt else 0 end) '数学',

max(case subject when '物理' then resuilt else 0 end) '物理'

from student group by name

 

🚩 使用if语句
大体同case when

select name,

max(if(subject = '语文',resuilt,0)) '语文'

from student group by name

 

🚩 动态拼接sql语句,不管多少行都会转列
set @sql = null;

select group_concat(distinct concat('max(if(a.subject = ''',a.subject,''', a.resuilt, 0)) as ''',a.subject, '''')) into @sql from student a;

set @sql = concat('select name,', @sql, 'from student a group by a.name' );

prepare stmt from @sql; -- 动态生成脚本,预备一个语句

execute stmt; -- 动态执行脚本,执行预备的语句

deallocate prepare stmt; -- 释放预备的语句

 

扩展分析

mysql的列转行为什么一定要用sum 或者max

遇到这种问题我们可以通过调试sql,来解决我们遇到的疑惑。

😍 二、列转行
🍀需求

 

转换为

 

select
name,
'语文' as subject,
chinese as resuilt
from -- 注意这里正常应该是from后直接跟一个表 偷懒不想创建表结构 直接用的子查询(行转列的代码)
(select
name,
max(case subject when '语文' then resuilt else 0 end) 'chinese',
max(case subject when '数学' then resuilt else 0 end) 'math',
max(case subject when '物理' then resuilt else 0 end) 'physics'
from student group by name
) t

union all

select
name,
'数学' as subject,
math as resuilt
from -- 注意这里正常应该是from后直接跟一个表 偷懒不想创建表结构 直接用的子查询(行转列的代码)
(select
name,
max(case subject when '语文' then resuilt else 0 end) 'chinese',
max(case subject when '数学' then resuilt else 0 end) 'math',
max(case subject when '物理' then resuilt else 0 end) 'physics'
from student group by name
) t

union all

select
name,
'物理' as subject,
physics as resuilt
from -- 注意这里正常应该是from后直接跟一个表 偷懒不想创建表结构 直接用的子查询(行转列的代码)
(select
name,
max(case subject when '语文' then resuilt else 0 end) 'chinese',
max(case subject when '数学' then resuilt else 0 end) 'math',
max(case subject when '物理' then resuilt else 0 end) 'physics'
from student group by name
) t

 

 

总结

行转列,使用case…when分情况查询数据,group by和sum/max进行筛选

列转行,查询需要的每列数据使用union或者union all求并集

😍 三、多列转一行
🍀需求

 

变为

 

select name,GROUP_CONCAT(`subject`,':',resuilt) '成绩' from student group by name

 

GROUP_CONCAT(expr)该函数将非空列值按照分组条件进行合并并最终返回。如果有空值,则返回为空

😍 四、一行转多列
🍀需求

 

变为

 

a表

select
name,
marks,
case
when locate('语文',marks) > 0 then substring_index(substring_index(marks,'语文:',-1),',',1) else 0 end
as 语文 ,
case
when locate('数学',marks) > 0 then substring_index(substring_index(marks,'数学:',-1),',',1) else 0 end
as 数学 ,
case
when locate('物理',marks) > 0 then substring_index(substring_index(marks,'物理:',-1),',',1) else 0 end
as 物理 ,
case
when locate('历史',marks) > 0 then substring_index(substring_index(marks,'历史:',-1),',',1) else 0 end
as 历史
from
(select
name,
GROUP_CONCAT(subject,':',resuilt) marks
from
student group by name) a


上面只是第一步 举例 要求还差一步 使用union all 继续加工sql

b表

select
name,
'语文' subject,
语文 score
from
(a表) b

union all

select
name,
'数学' subject,
数学 score
from
(a表) b

union all

select
name,
'物理' subject,
物理 score
from
(a表) b

union all

select
name,
'历史' subject,
历史 score
from
(a表) b


Locate函数主要的作用是判断一个字符串是否包含另一个字符串,如

Locate(str,sub) > 0,表示sub字符串包含str字符串;

Locate(str,sub) = 0,表示sub字符串不包含str字符串。

substring_index(参数str,参数delim,参数count)

str :要处理的字符串

delim:分隔符

count:计数

也就是说,如果count是正数,那么就是从左往右数,第N个分隔符的左边的全部内容! 相反,如果是负数,那么就是从右边开始数,第N个分隔符右边的所有内容,
————————————————
版权声明:本文为CSDN博主「妙趣生花」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/nanyangnongye/article/details/125217634

posted on   白露~  阅读(6792)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
历史上的今天:
2021-07-15 告别编码5分钟,命名2小时!史上最全的Java命名规范参考!
2021-07-15 史上最全常用正则表达式大全
2021-07-15 JAVA中不要用e.printStackTrace()
2021-07-15 JAVA中不要用e.printStackTrace()
2021-07-15 为什么尽量不用e.printStackTrace
2021-07-15 java返回集合为null还是空集合以及空集合的三种写法
2021-07-15 IntelliJ IDEA使用技巧——常用快捷键Mac篇
点击右上角即可分享
微信分享提示