你真的会玩SQL吗?透视转换的艺术
透视转换是一种行列互转的技术,在转过程中可能执行聚合操作,应用非常广泛。
本章与 你真的会玩SQL吗?数据聚合 内容比较重要,还涉及到 你真的会玩SQL吗?Case的用法 的内容,都可以一起看。
下面的例子将使用OpenSchema表,运行创建表:
CREATE TABLE OpenSchema( objectid INT NOT NULL, attribute VARCHAR(30) NOT NULL , VALUE SQL_VARIANT NOT NULL, PRIMARY KEY (objectid,attribute) ) GO INSERT INTO OpenSchema(objectid,attribute,VALUE) VALUES (1,N'attr1',CAST(CAST('ABC' AS VARCHAR(10)) AS SQL_VARIANT)), (1,N'attr2',CAST(CAST(10 AS INT) AS SQL_VARIANT)), (1,N'attr3',CAST(CAST('20070101' AS SMALLDATETIME) AS SQL_VARIANT)), (2,N'attr2',CAST(CAST(12 AS INT) AS SQL_VARIANT)), (2,N'attr3',CAST(CAST('20090101' AS SMALLDATETIME) AS SQL_VARIANT)), (2,N'attr4',CAST(CAST('Y' AS CHAR(1)) AS SQL_VARIANT)), (2,N'attr5',CAST(CAST(13.7 AS NUMERIC(9,3)) AS SQL_VARIANT)), (3,N'attr1',CAST(CAST('xyz' AS VARCHAR(10)) AS SQL_VARIANT)), (3,N'attr2',CAST(CAST(20 AS INT) AS SQL_VARIANT)), (3,N'attr3',CAST(CAST('20080101' AS SMALLDATETIME) AS SQL_VARIANT))
将会得到以下输出:
以上VALUE属性保存了多个不同数据类型的值,可以实现要添加新的属性时不用添加列,直接保存。
但是这样查询我们希望把数据旋转为每个属性占一列的传统方式,然后再保存到临时表中处理后续查询称之为透视转换技术。在这里需要回看一下 你真的会玩SQL吗?之逻辑查询处理阶段 对于理解透视转换的步骤是有帮助的。
来看一看经典的行转列实例,如要得到下面的结果怎么做:
透视转换的步骤:
- 分组:这里需要为每个对象从多个基础行来创建单独的一列数据,这意味着要对行进行分组,这里依据的是objectid列。
- 扩展:从结果列考虑每个唯一的属性都需要一个结果列,对应的是attribute列。这里是attr1,attr2……attr5,列中包含5个表达式。
- 聚合:从一组NULL值和已知值中提取出已知值,这就需要使用聚合操作,提取已知值技巧就是使用MAX或MIN函数,这两个会忽略NULL,并返回一个非NULL值,国为只包含一个值的集合最大值和最小值就是这个值。此处对就列是VALUE列。每组中若包含多个非NULL值 ,视情况也可用SUM/AVG。
参考SQL:
这里也可以用PIVOT,不过PIVOT不支持动态透视转换,除了使代码更短外没有什么显著差异,这里就不演示了。
逆透视转换
即列旋转行,常用于规范化数据,如将上面的结果逆转换。
创建表:
CREATE TABLE PvtOpenSchema( objectid INT NOT NULL, attr1 VARCHAR(10) NULL , attr2 VARCHAR(10) NULL , attr3 VARCHAR(10) NULL , attr4 VARCHAR(10) NULL , attr5 VARCHAR(10) NULL )
将上面的结果插入此表:
INSERT INTO PvtOpenSchema ( objectid,attr1,attr2,attr3,attr4,attr5 ) SELECT objectid ,MAX(CASE WHEN attribute = 'attr1' THEN CAST( VALUE AS VARCHAR(10)) END) AS attr1 ,MAX(CASE WHEN attribute = 'attr2' THEN CAST( VALUE AS VARCHAR(10)) END) AS attr2 ,MAX(CASE WHEN attribute = 'attr3' THEN CAST( VALUE AS VARCHAR(10)) END) AS attr3 ,MAX(CASE WHEN attribute = 'attr4' THEN CAST( VALUE AS VARCHAR(10)) END) AS attr4 ,MAX(CASE WHEN attribute = 'attr5' THEN CAST( VALUE AS VARCHAR(10)) END) AS attr5 FROM OpenSchema GROUP BY objectid
结果:
若做到逆转换,将每个objectid 和每个attribute生成结果集中的一行
第一步是为每个甚而行生成5个属性副本,可以通过基础表和每个属性占一行虚拟辅助表执行交叉联接来实现,然后用select 返回objectid和attribute,用case计算值。
可能数据源中会得到与NULL值,如1的attr4,所以还需要对结果进行过滤掉Value为NULL的。
代码如下:
SELECT objectid ,attribute ,VALUE FROM ( SELECT objectid ,attribute ,CASE attributeWHEN 'attr1' THEN attr1WHEN 'attr2' THEN attr2WHEN 'attr3' THEN attr3WHEN 'attr4' THEN attr4WHEN 'attr5' THEN attr5END AS VALUEFROM PvtOpenSchemaCROSS JOIN ( SELECT 'attr1' AS attributeUNION ALLSELECT 'attr2'UNION ALLSELECT 'attr3'UNION ALLSELECT 'attr4'UNION ALLSELECT 'attr5') AS attributes) AS T WHERE VALUE IS NOT NULL
这里可以使用UNPIVOT表运算符,查询将更简单:
SELECT objectid ,attribute ,VALUE FROM PvtOpenSchema UNPIVOT ( VALUE FOR attribute IN ( attr1, attr2, attr3, attr4, attr5 ) ) AS a
UNPIVOT会在一个逻辑处理中删除NULL行。
以上只是一个简单的示例,即使现在理解了但在多变的实际应用可能就会迷惘,那时再来对比看看此例。
练习:
姓名 科目 成绩张三 语文 80张三 数学 90张三 物理 85李四 语文 85李四 物理 82李四 英语 90李四 政治 70王五 英语 90
将上表转换为:
姓名 数学 物理 英语 语文 政治 李四 0 82 90 85 70王五 0 0 90 0 0张三 90 85 0 80 0
转载于:https://www.cnblogs.com/8080zl/p/8603170.html
你真的会玩SQL吗?透视转换的艺术相关推荐
- 你真的会玩SQL吗?EXISTS和IN之间的区别
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- 你真的会玩SQL吗?和平大使 内连接、外连接
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- 你真的会玩SQL吗?简单的数据修改
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- 你真的会玩SQL吗?Case也疯狂
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- 你真的会玩SQL吗?玩爆你的数据报表之存储过程编写(上)
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- 你真的会玩SQL吗?你所不知道的 数据聚合
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- 你真的会玩SQL吗?玩爆你的数据报表之存储过程编写(下)
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- 你真的会玩SQL吗?Case的用法(转)
今天来总结整理一下Case,因为SQL查询中用得最多的逻辑判断. Case具有两种格式.简单Case函数和Case搜索函数. --简单Case函数 CASE sex WHEN '1' THEN '男' ...
- 你真的会玩SQL吗?内连接、外连接
大多数人一般写多表查询会这样写select * from tbA ,tbB 没有用到JOIN关键字,太Low了,官网标准建议是用JOIN明确表间的关系,下面具体来讲. 连接类型: 交叉联接 得到所连 ...
最新文章
- redis 主从配置_应用 | Redis实现 主从,单例,集群,哨兵,配置应用
- c++二进制文件java读取int_吃透Java基础十二:IO
- ffmpeg 为取经而来_伊力特的英雄情结从何而来?
- php 截取某个字符,PHP_php截取指定2个字符之间字符串的方法,本文实例讲述了php截取指定2个 - phpStudy...
- DB2数据库备份恢复
- Windows XP操作系统中的禁忌
- 对 React 组件进行单元测试(unit testing)
- 【算法】—— 最大子序列和问题
- 好的架构不是设计出来的,而是演进出来的
- 要用“+智能”强身健体,“心脏”做好准备了吗
- 3项目里面全局用less变量 cli vue_Vue.js构建工具比较
- 一、绘制不同类别特征均值标准差直方图
- echarts 柱状图圆柱_使用echarts画柱状图
- 正方教务系统php登陆,正方教务管理系统最新版无条件注入GetShell | wooyun-2015-0122523| WooYun.org...
- 高中数学必修3知识点总结归纳:第三章概率
- 微信小程序出现报错:Uncaught ReferenceError: __g is not defined
- 解决IE浏览器下img src通过请求方式不显示图片的问题
- c语言按位取反 补码,求C语言 按位取反?
- S2B2C社交电商系统怎么开发?
- You are running the esm-bundler build of vue-i18n. It is recommended to configure your bundler to ex