透视转换是一种行列互转的技术,在转过程中可能执行聚合操作,应用非常广泛。

本章与 你真的会玩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吗?之逻辑查询处理阶段 对于理解透视转换的步骤是有帮助的。

来看一看经典的行转列实例,如要得到下面的结果怎么做:

透视转换的步骤:

  1. 分组:这里需要为每个对象从多个基础行来创建单独的一列数据,这意味着要对行进行分组,这里依据的是objectid列。
  2. 扩展:从结果列考虑每个唯一的属性都需要一个结果列,对应的是attribute列。这里是attr1,attr2……attr5,列中包含5个表达式。
  3. 聚合:从一组NULL值和已知值中提取出已知值,这就需要使用聚合操作,提取已知值技巧就是使用MAX或MIN函数,这两个会忽略NULL,并返回一个非NULL值,国为只包含一个值的集合最大值和最小值就是这个值。此处对就列是VALUE列。每组中若包含多个非NULL值 ,视情况也可用SUM/AVG。

参考SQL:

 View Code

这里也可以用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吗?透视转换的艺术相关推荐

  1. 你真的会玩SQL吗?EXISTS和IN之间的区别

    你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...

  2. 你真的会玩SQL吗?和平大使 内连接、外连接

    你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...

  3. 你真的会玩SQL吗?简单的数据修改

    你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...

  4. 你真的会玩SQL吗?Case也疯狂

    你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...

  5. 你真的会玩SQL吗?玩爆你的数据报表之存储过程编写(上)

    你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...

  6. 你真的会玩SQL吗?你所不知道的 数据聚合

    你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...

  7. 你真的会玩SQL吗?玩爆你的数据报表之存储过程编写(下)

    你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...

  8. 你真的会玩SQL吗?Case的用法(转)

    今天来总结整理一下Case,因为SQL查询中用得最多的逻辑判断. Case具有两种格式.简单Case函数和Case搜索函数. --简单Case函数 CASE sex WHEN '1' THEN '男' ...

  9. 你真的会玩SQL吗?内连接、外连接

    大多数人一般写多表查询会这样写select * from tbA ,tbB  没有用到JOIN关键字,太Low了,官网标准建议是用JOIN明确表间的关系,下面具体来讲. 连接类型: 交叉联接 得到所连 ...

最新文章

  1. redis 主从配置_应用 | Redis实现 主从,单例,集群,哨兵,配置应用
  2. c++二进制文件java读取int_吃透Java基础十二:IO
  3. ffmpeg 为取经而来_伊力特的英雄情结从何而来?
  4. php 截取某个字符,PHP_php截取指定2个字符之间字符串的方法,本文实例讲述了php截取指定2个 - phpStudy...
  5. DB2数据库备份恢复
  6. Windows XP操作系统中的禁忌
  7. 对 React 组件进行单元测试(unit testing)
  8. 【算法】—— 最大子序列和问题
  9. 好的架构不是设计出来的,而是演进出来的
  10. 要用“+智能”强身健体,“心脏”做好准备了吗
  11. 3项目里面全局用less变量 cli vue_Vue.js构建工具比较
  12. 一、绘制不同类别特征均值标准差直方图
  13. echarts 柱状图圆柱_使用echarts画柱状图
  14. 正方教务系统php登陆,正方教务管理系统最新版无条件注入GetShell | wooyun-2015-0122523| WooYun.org...
  15. 高中数学必修3知识点总结归纳:第三章概率
  16. 微信小程序出现报错:Uncaught ReferenceError: __g is not defined
  17. 解决IE浏览器下img src通过请求方式不显示图片的问题
  18. c语言按位取反 补码,求C语言 按位取反?
  19. S2B2C社交电商系统怎么开发?
  20. You are running the esm-bundler build of vue-i18n. It is recommended to configure your bundler to ex

热门文章

  1. 数据库设计精选视频_11种精选工具和服务,可改善您的设计工作
  2. angularjs 实例_AngularJS服务示例教程
  3. 14-9-25日jenkins部署到tomcat的错误日志
  4. powershell文章汇总
  5. 找工作?最容易遇到的Java面试题
  6. java新职篇:面向对象之抽象
  7. 物联网中间件的未来是云计算技术为中心和混合结构
  8. LoadRunner调用Oracle存储过程
  9. tcp协议报文和三次握手与四次挥手
  10. linux命令别名永久生效