T-SQL——数据透视和逆透视

  • 按照数据库第一范式:一个实体中不应该包含重复类型的特性,对应到表就是:类似的值不能在一个表的多个列上重复

  • 创建表应该按照一维表的格式创建,记录产生信息。

  • 若是建表的时候创建为二维表,将所有的种类做为字段,则可能出现表的字段非常的多,当种类有所添加的时候,后续还要继续添加字段。

  • 一维表方便存储数据,同样也是便于后期查询

  • 二维表可以直观的表现数据的信息,是用于展示的报表和报告


1. 透视转换

1.1 使用标准SQL进行数据透视

–注意这里实现业务场景,在CASE WHEN语句中

–我们应该使用默认的ELSE NULL ,而不是ELSE 0。没有数据是没有数据,0是0

SELECT Name,

SUM(CASE WHEN Subject =‘语文’ THEN Temp1.Scores ElSE NULL END) AS 语文 ,

SUM(CASE WHEN Subject =‘数学’ THEN Temp1.Scores ELSE NULL END) AS 数学 ,

SUM(CASE WHEN Subject =‘英语’ THEN Temp1.Scores ELSE NULL END) AS 英语

FROM Temp1 GROUP BY Temp1.Name

结果:

Name 英语 数学 语文


李四 60 70 90

张三 80 90 100

【说明】:使用标准的SQL语句进行数据的透视转换,我们可以直白的发现透视转换,是分为三个阶段的:

分组–>扩展–>聚合

以上例说明:

  • 分组:我们按照Name字段进行分组,使每一个用户产生一条记录

  • 使用GROUP BY实现分组

  • 扩展:扩展是对列的扩展,使用case语句, 对三个科目(语文,数学,英语)扩展为列

  • 使用SELECT 配合CASE WHEN实现

  • 聚合:按照分组依据进行聚合,这里按照Name字段分组,使用SUM函数对Scores字段聚合

  • 使用任一聚合函数聚合

对照上述三个逻辑步骤:

  • Name字段:分组依据字段(分组元素)。指定要用于透视结果表的左侧列,也称为设置键

  • Subject字段:待扩展字段(待扩展元素)。透视结果表中的列头所在的列,也称为透视键,"语文,数学,英语"为目标列的列名的集合,又称为透视输出列

  • Scores字段:聚合字段(聚合元素)。透视结果表中的主要显示的数据就是来自这个字段的值,又称为透视值

1.2 使用T-SQL中pivot函数进行数据透视

【函数】:pivot

【作用】:行转列函数,SQL Server2005

【语法】:pivot(任一聚合函数 for 需转列的值所在列名 in (需转为列名的值))

【用法】:select …from table pivot(……) as T

【示例1】:

现有一张成绩表,表中记录了每个学生每科目的成绩,如下。

现在需要将科目作为列头,统计每个学生的成绩。

WITH Temp1 AS

(

SELECT ‘张三’ AS Name, ‘语文’ AS Subject, 100 AS Scores

UNION ALL

SELECT ‘张三’ AS Name, ‘数学’ AS Subject, 90 AS Scores

UNION ALL

SELECT ‘张三’ AS Name, ‘英语’ AS Subject, 80 AS Scores

UNION ALL

SELECT ‘李四’ AS Name, ‘语文’ AS Subject, 90 AS Scores

UNION ALL

SELECT ‘李四’ AS Name, ‘数学’ AS Subject, 70 AS Scores

UNION ALL

SELECT ‘李四’ AS Name, ‘英语’ AS Subject, 60 AS Scores

)

SELECT T.Name, T.英语, T.数学, T.语文 FROM Temp1 PIVOT(SUM(Scores) FOR [Subject] IN (语文,数学,英语)) T;

结果:

Name 英语 数学 语文


李四 60 70 90

张三 80 90 100

【注意1】:

我们是按照以下格式:

select …from table pivot(任意聚合函数(聚合字段) for 待扩展字段名 in (待扩展元素集)) as T

使用pivot对table进行数据透视

若是table中的字段既不是聚合字段,又不是待扩展字段,则会默认为pivot函数中的分组依据的字段。

所以使用pivot函数进行数据透视的结果集一般不会是数据库中的原表,而是一个查询出的特定字段的结果集

【注意2】:

若待扩展元素集是非常规标识符,比如说日期或数字开头的其他类型数据,则我们需要使用方括号将每一个待扩展展元素括起。

【示例2】:

现在在测试数据1中添加一个Class字段,使用pivot函数透视数据

WITH Temp1 AS

(

SELECT ‘张三’ AS Name, ‘语文’ AS Subject, 100 AS Scores,‘八年级一班’ AS Class

UNION ALL

SELECT ‘张三’ AS Name, ‘数学’ AS Subject, 90 AS Scores,‘三年级二班’ AS Class

UNION ALL

SELECT ‘张三’ AS Name, ‘英语’ AS Subject, 80 AS Scores,‘三年级二班’ AS Class

UNION ALL

SELECT ‘李四’ AS Name, ‘语文’ AS Subject, 90 AS Scores,‘三年级二班’ AS Class

UNION ALL

SELECT ‘李四’ AS Name, ‘数学’ AS Subject, 70 AS Scores,‘三年级二班’ AS Class

UNION ALL

SELECT ‘李四’ AS Name, ‘英语’ AS Subject, 60 AS Scores,‘三年级二班’ AS Class

)

SELECT T.Name,T.Class, T.英语, T.数学, T.语文 FROM Temp1 PIVOT(SUM(Scores) FOR [Subject] IN (语文,数学,英语)) T;

结果:

Name Class 英语 数学 语文


张三 八年级一班 NULL NULL 100

李四 三年级二班 60 70 90

张三 三年级二班 80 90 NULL

【说明】:结果集Temp1中的class既不是聚合字段,也不是待扩展字段,所以会被默认为是分组依据!

而往往,我们期望的分组依据只要Name字段,

所以一般都是建议不要直接对数据库中的基础表进行透视操作,而是将特定字段查询出来作为一个表结果集,之后在对这个结果集进行透视操作。

1.3 关于 待扩展元素集合获取的方式


2. 逆透视转换

【逆透视】:逆透视转换将来自单个记录中多个列的值扩展为单个列中具有同样值的多个记录,使得非规范的数据集成为较规范的版本。

2.1 使用标准SQL进行数据逆透视

数据的逆透视也是分为三步:请客,斩首,收下当狗

啊唾,不对,应该是是:生成副本–>提取元素–>删除不相干交叉

WITH Temp AS

(

–测试数据集

SELECT ‘张三’ AS Name, ‘八年级二班’ AS Class, NULL AS 英语, NULL AS 数学, 100 AS 语文

UNION ALL

SELECT ‘李四’ AS Name, ‘三年级二班’ AS Class, 60 AS 英语, 70 AS 数学, 90 AS 语文

UNION ALL

SELECT ‘张三’ AS Name, ‘三年级二班’ AS Class, 80 AS 英语, 90 AS 数学, NULL AS 语文

)

,Temp1 AS

(

–为每一行生成副本

–与需要逆透视的列交叉连接获取笛卡尔积

SELECT * FROM Temp CROSS JOIN( VALUES(‘英语’),(‘数学’),(‘语文’)) AS T(SubjectName)

–结果

–Name Class 英语 数学 语文 SubjectName

–张三 八年级二班 NULL NULL 100 英语

–张三 八年级二班 NULL NULL 100 数学

–张三 八年级二班 NULL NULL 100 语文

–李四 三年级二班 60 70 90 英语

–李四 三年级二班 60 70 90 数学

–李四 三年级二班 60 70 90 语文

–张三 三年级二班 80 90 NULL 英语

–张三 三年级二班 80 90 NULL 数学

–张三 三年级二班 80 90 NULL 语文

)

,Temp2 AS

(

–当前行SubjectName为英语则取英语列

SELECT Name,Class,Temp1.SubjectName,

CASE Temp1.SubjectName

WHEN ‘英语’ THEN

英语

WHEN ‘数学’ THEN

数学

WHEN ‘语文’ THEN

语文

END AS Scores

FROM Temp1

–结果

–Name Class SubjectName Scores

–张三 八年级二班 英语 NULL

–张三 八年级二班 数学 NULL

–张三 八年级二班 语文 100

–李四 三年级二班 英语 60

–李四 三年级二班 数学 70

–李四 三年级二班 语文 90

–张三 三年级二班 英语 80

–张三 三年级二班 数学 90

–张三 三年级二班 语文 NULL

)

–删除不相关交叉行(排除NULL值行)

SELECT * FROM Temp2 WHERE Temp2.Scores IS NOT NULL

–结果

–Name Class SubjectName Scores

–张三 八年级二班 语文 100

–李四 三年级二班 英语 60

–李四 三年级二班 数学 70

–李四 三年级二班 语文 90

–张三 三年级二班 英语 80

–张三 三年级二班 数学 90

2.2 使用T-SQL中unpivot函数进行数据逆透视

【函数】:unpivot

【作用】:列转行函数,SQL Server2005

【语法】:unpivot(作为属性值列的列名 for 属性名 in (同一属性的列名))

【用法】:select …from table unpivot(……) as T

【示例1】

WITH Temp2 AS

(

SELECT ‘张三’ AS Name, ‘八年级二班’ AS Class, NULL AS 英语, NULL AS 数学, 100 AS 语文

UNION ALL

SELECT ‘李四’ AS Name, ‘三年级二班’ AS Class, 60 AS 英语, 70 AS 数学, 90 AS 语文

UNION ALL

SELECT ‘张三’ AS Name, ‘三年级二班’ AS Class, 80 AS 英语, 90 AS 数学, NULL AS 语文

)

SELECT * FROM Temp2 UNPIVOT(Socore FOR Subject IN(英语, 数学, 语文)) T;

结果:

Name Class Socore Subject


张三 八年级二班 100 语文

李四 三年级二班 60 英语

李四 三年级二班 70 数学

李四 三年级二班 90 语文

张三 三年级二班 80 英语

张三 三年级二班 90 数学


3. 透视之后再逆透视数据信息减少

上面的示例数据中,将原数据(测试数据1)进行透视操作,变为测试数据2。将测试数据2逆透视结果变回了测试数据1。

这只是巧合而已,因为我们的测试数据1中没有出现相同属性(同一个人相同科目)的多条记录:

比如说,如果李四有两条英语成绩如下:

WITH Temp1 AS

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

由于篇幅原因,就不多做展示了
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
内容对你有帮助,可以扫码获取!!(备注Java获取)**

img

最后

[外链图片转存中…(img-hgQvnQAV-1713344127614)]

[外链图片转存中…(img-5UuX3xiY-1713344127614)]

[外链图片转存中…(img-ZIMSepJF-1713344127615)]

[外链图片转存中…(img-YPiLMjYH-1713344127615)]

[外链图片转存中…(img-YDxYjJM7-1713344127615)]

[外链图片转存中…(img-Sof7ZrNA-1713344127615)]

由于篇幅原因,就不多做展示了
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 14
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值