你真的会玩SQL吗?透视转换的艺术
你真的会玩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('' AS SMALLDATETIME) AS SQL_VARIANT)),
(2,N'attr2',CAST(CAST(12 AS INT) AS SQL_VARIANT)),
(2,N'attr3',CAST(CAST('' 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('' AS SMALLDATETIME) AS SQL_VARIANT))
将会得到以下输出:

以上VALUE属性保存了多个不同数据类型的值,可以实现要添加新的属性时不用添加列,直接保存。
但是这样查询我们希望把数据旋转为每个属性占一列的传统方式,然后再保存到临时表中处理后续查询称之为透视转换技术。在这里需要回看一下 你真的会玩SQL吗?之逻辑查询处理阶段 对于理解透视转换的步骤是有帮助的。
来看一看经典的行转列实例,如要得到下面的结果怎么做:

透视转换的步骤:
- 分组:这里需要为每个对象从多个基础行来创建单独的一列数据,这意味着要对行进行分组,这里依据的是objectid列。
- 扩展:从结果列考虑每个唯一的属性都需要一个结果列,对应的是attribute列。这里是attr1,attr2……attr5,列中包含5个表达式。
- 聚合:从一组NULL值和已知值中提取出已知值,这就需要使用聚合操作,提取已知值技巧就是使用MAX或MIN函数,这两个会忽略NULL,并返回一个非NULL值,国为只包含一个值的集合最大值和最小值就是这个值。此处对就列是VALUE列。每组中若包含多个非NULL值 ,视情况也可用SUM/AVG。
参考SQL:
SELECT objectid ,
MAX(CASE WHEN attribute = 'attr1' THEN VALUE
END) AS attr1 ,
MAX(CASE WHEN attribute = 'attr2' THEN VALUE
END) AS attr2 ,
MAX(CASE WHEN attribute = 'attr3' THEN VALUE
END) AS attr3 ,
MAX(CASE WHEN attribute = 'attr4' THEN VALUE
END) AS attr4 ,
MAX(CASE WHEN attribute = 'attr5' THEN VALUE
END) AS attr5
FROM OpenSchema
GROUP BY objectid
这里也可以用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 attribute
WHEN 'attr1' THEN attr1
WHEN 'attr2' THEN attr2
WHEN 'attr3' THEN attr3
WHEN 'attr4' THEN attr4
WHEN 'attr5' THEN attr5
END AS VALUE
FROM PvtOpenSchema
CROSS JOIN ( SELECT 'attr1' AS attribute
UNION ALL
SELECT 'attr2'
UNION ALL
SELECT 'attr3'
UNION ALL
SELECT 'attr4'
UNION ALL
SELECT '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
你真的会玩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吗?查询指定节点及其所有父节 ...
- 你真的会玩SQL吗?EXISTS和IN之间的区别
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- 你真的会玩SQL吗?无处不在的子查询
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- 你真的会玩SQL吗?Case也疯狂
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- 你真的会玩SQL吗?表表达式,排名函数
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
随机推荐
- iOS热更新-8种实现方式
一.JSPatch 热更新时,从服务器拉去js脚本.理论上可以修改和新建所有的模块,但是不建议这样做. 建议 用来做紧急的小需求和 修复严重的线上bug. 二.lua脚本 比如: wax.热更新时,从 ...
- 【Win 10 应用开发】在App所在的进程中执行后台任务
在以往版本中,后台任务都是以独立的专用进程来运行,因此,定义后台任务代码的类型都要位于 Windows 运行时组件项目中. 不过,在14393中,SDK 作了相应的扩展,不仅支持以前的独立进程中运行后 ...
- 【NLP】前戏:一起走进条件随机场(一)
前戏:一起走进条件随机场 作者:白宁超 2016年8月2日13:59:46 [摘要]:条件随机场用于序列标注,数据分割等自然语言处理中,表现出很好的效果.在中文分词.中文人名识别和歧义消解等任务中都有 ...
- 简记某WebGIS项目的优化之路
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1. 背景 该项目为研究生时的老师牵头,个人已毕业数年,应老师要求协助其 ...
- sql的那些事(一)
一.概述 书写sql是我们程序猿在开发中必不可少的技能,优秀的sql语句,执行起来吊炸天,性能杠杠的.差劲的sql,不仅使查询效率降低,维护起来也十分不便.一切都是为了性能,一切都是为了业务,你觉得你 ...
- CSS知识总结(九)
CSS常用样式 10.自定义动画 1)关键帧(keyframes) 被称为关键帧,其类似于Flash中的关键帧. 在CSS3中其主要以“@keyframes”开头,后面紧跟着是动画名称加上一对花括号“ ...
- 自己写的数据交换工具——从Oracle到Elasticsearch
先说说需求的背景,由于业务数据都在Oracle数据库中,想要对它进行数据的分析会非常非常慢,用传统的数据仓库-->数据集市这种方式,集市层表会非常大,查询的时候如果再做一些group的操作,一个 ...
- java面向对象六原则一法则
1. 单一职责原则:一类只做它该做的事. 2. 里氏替换原则:子类必须能够替换基类(父类),否则不应当设计为其子类. 3. 依赖倒换原则:设计要依赖于抽象而不是具体化. 4. 接口隔离原则:接口要小而 ...
- AspNetPager分页控件样式的使用
分页是Web应用程序中最常用到的功能之一,AspNetPager 简单实用,应用到项目后台中,棒极了! 自定义样式: <style type="text/css"> ...
- 为什么很多SaaS企业级产品都熬不过第一年
因工作缘由,笔者与周边数位SaaS企业级应用的创始人.运营负责人有过深入接触,发现一个有趣的现象:刚起步时,蓝图远志.规划清晰,但是一路下来,却异常艰难,有些甚至熬不过第一年,就关门歇业. 2015年 ...