一、场景
在成绩单p1中,我想让同一个人的成绩合并到一行,并显示其语文数学英语的成绩如p2,
这种情况下如果需要对两种形式互相转换的话就是所谓的行转列与列转行了


二、语法说明
- 行转列需要用到语法
case条件分支 - 列转行用到
union all
case介绍:
概念:CASE 是 SQL 的条件分支表达式,相当于编程语言里的if-elif-else,用于在查询中做条件判断、数据转换、分组统计,是 DQL 查询的核心工具之一。
语法:
CASE
WHEN 条件1 THEN 结果1
WHEN 条件2 THEN 结果2
...
ELSE 默认结果
ENDunion介绍:
概念:合并 两条 / 多条 SELECT 查询结果,自动去重。
union与union all都是输出内容的拼接,union会对输出的内容进行去重排序,而union all直接对输出内容拼接,不做任何处理,大白话就是讲两个sql查询语句拼到一起输出
值得注意的是:
1.前后sql查询的 列数量必须相同
2.对应列的数据类型 必须兼容
3.列名以 第一条 SELECT 的列名为准
语法:
SELECT 列1, 列2 FROM 表1
UNION
SELECT 列1, 列2 FROM 表2;三、执行逻辑
先分别建两个表
score表为行转列测试表
score_unpiove为列转行测试表
-- 创建表
CREATE TABLE score (
name VARCHAR(10),
subject VARCHAR(10),
score INT
);
-- 插入数据
INSERT INTO score VALUES ('张三', '语文', 80);
INSERT INTO score VALUES ('张三', '数学', 90);
INSERT INTO score VALUES ('张三', '英语', 85);
INSERT INTO score VALUES ('李四', '语文', 70);
INSERT INTO score VALUES ('李四', '数学', 60);
CREATE table score_unpiove
SELECT name 姓名,
max(case when subject='语文' then score END) as 语文,
max(case when subject='数学' then score END) as 数学,
max(case when subject='英语' then score END) as 英语
FROM score
GROUP BY name;
SELECT * FROM score_unpiove;行转列逻辑:
直接先看代码
-- 先以求每个学生的语文成绩为例
SELECT
name,
MAX(CASE WHEN subject = '语文' THEN score END) AS 语文
FROM score
GROUP BY name;
-- 1.先按名字分组,张三是一组,李四是一组
-- 2.在每组内case每行去筛选subject = '语文'并返回该行的score
-- 3.对每组返回的结果进行聚合取值、张三组返回结果为(80,null,null)取max之后返回80
-- 4.对数学。英语组重复该操作即可
MAX(CASE WHEN subject = '数学' THEN score END) AS 数学
MAX(CASE WHEN subject = '英语' THEN score END) AS 英语
-- 5.最终程序为:
SELECT
name,
MAX(CASE WHEN subject = '语文' THEN score END) AS 语文,
MAX(CASE WHEN subject = '数学' THEN score END) AS 数学,
MAX(CASE WHEN subject = '英语' THEN score END) AS 英语
FROM score
GROUP BY name;1.先group by 分组
2.对每组里每行特定字段依次进行case条件判断并返回值,如果该行内没有找到该特定字段则返回null,(学习的例子中该语文字段值返回了(80,null,null))
3.对返回的所有结果进行聚合取值,(MAX、SUM、MIN结果都一样),但是我们偏向于使用MAX
4.以上面步骤依次对其他列进行相同处理
列转行逻辑:
相对比case语句,列转行就相对来说简单一些了
还是先看代码
-- 先求出姓名,自定义学科名 , 以及挂科成绩
select name,'语文' as subject , chinese as score from score;
-- 改语句结果如下
-- name , subject , score
-- 张三 语文 80
-- 李四 语文 70
-- 同理:将数学,英语的分拼接即可
select name,'语文' as subject , chinese as score from score
union all
select name,'数学' as subject , math as score from score
union all
select name,'英语' as subject , english as score from score;逻辑是:
把"语文列"单独查出来,变成行
把"数学列"单独查出来,变成行
把"英语列"单独查出来,变成行
用 UNION ALL 把三部分上下拼接
我们只需要按如图所示的方案,分门别类的把字段值拿出来再用union all直接拼接到一起即可