原文:SQL点滴19—T-SQL中的透视和逆透视

  

透视

今天抽一点时间来看看透视和逆透视语句,简单的说就是行列转换。假设一个销售表中存放着产品号,产品折扣,产品价格三个列,每一种产品号可能有多种折扣,每一种折扣只对应一个产品价格。下面贴出建表语句和插入数据语句。

1 create table SalesOrderDetail(
2 ProductID int /*unique多谢wuu00的提醒*/,
3 UnitPriceDiscount float,
4 ProductPrice float
5 )
6  insert into SalesOrderDetail values
7 (711,.00,12),
8 (711,.00,13),
9 (711,.02,17),
10 (711,.02,16),
11 (711,.05,19),
12 (711,.05,20),
13 (711,.10,21),
14 (711,.10,22),
15 (711,.15,23),
16 (711,.15,24),
17 (747,.00,41),
18 (747,.00,42),
19 (747,.02,45),
20 (747,.02,46),
21 (776,.20,50),
22 (776,.20,49),
23 (776,.35,52),
24 (776,.35,53)

首先来看一条查询语句

1 select ProductID,UnitPriceDiscount,SUM(ProductPrice) as SumPrice
2  from SalesOrderDetail
3  group by ProductID,UnitPriceDiscount
4 order by ProductID,UnitPriceDiscount

这条语句查询每一种产品针对每一种折扣的价钱总和,查询结果如下图1

图1

  

从图中我们可以看出771号产品有4种折扣,747号产品有2种折扣,776号产品有2种折扣。现在如果我们想知道每一种产品折扣,每一种产品的销售总价是多少,如下图2

图2

  

如图对于折扣0,产品711的总价是25,对以折扣0.02,产品711的总价是33等等不再列举。原来的行是产品号,现在产品号变成了列,原来的折扣变成了现在的第一列。这就是数据透视的效果。下面我们开看看是这个效果是如何用语句实现的。

1 select * from
2 (select sod.ProductPrice,sod.ProductID,sod.UnitPriceDiscount from SalesOrderDetail sod) so
3 pivot
4 (
5 sum(so.ProductPrice) for so.ProductID in([711],[747],[776])
6 ) as pt
7 order by UnitPriceDiscount

  

首选创建子查询(select sod.ProductPrice,sod.ProductID,sod.UnitPriceDiscount from SalesOrderDetail sod) so ,透视运算符要使用这个子查询中的数据进行聚合运算,此外输出显示也要用到子查询中的列。代码生成一个别名为so的表值表达式。在这个表中使用pivot在特定的列上进行聚合,这里是对so.ProductPrice进行聚合,聚合针对so.ProductID进行。在这个例子中对三种产品的中的每一种创建一个列。这个相当于group by,从so表达式中进行数据筛选。不过这里没有选出ProductPrice,仅仅生成每行三个列,每一种产品为一个列的结果集。因此带有povit的表值表达式生成一个临时的结果集,将这个结果集命名为pt,使用这个结果集生成我们需要的输出。如果想要得到一个更加合适的列名可以修改筛选条件。如下:

1 select pt.UnitPriceDiscount,[711] as Product711,[747] as Product747,[776] as Product747 from
2 (select sod.ProductPrice,sod.ProductID,sod.UnitPriceDiscount from SalesOrderDetail sod) so
3 pivot
4 (
5 sum(so.ProductPrice) for so.ProductID in([711],[747],[776])
6 ) as pt
7 order by UnitPriceDiscount

  

输出的结果如下图3

图3

  

逆透视

这次我们首先看语句和查询结果再分析,语句如下:

1 select ProductID,UnitPriceDiscount,ProductPrice
2 from
3 (select UnitPriceDiscount,Product711,Product747,Product776 from #Temp1) as up1
4 unpivot(ProductPrice for ProductID in(Product711,Product747,Product776)) as up2
5 order by ProductID

查询结果如下图4:



图4



首先我们来看看逆透视得到了一个什么样的结果。对于每一种产品的每一种折扣查询得到他们的合计售价,这个和上面图1中的结果是一样的,是的,它和透视之前的结果是相同的。逆透视和透视并不是完全相反。Pivot会执行聚合,把可能存在的多个行合并输出得到一行。由于已经进行了合并,unpivot无法重新生成原始的表值表达式,unpivot输入中的null值将在输出中消失,尽管在pivot操作之前输入中可能存在原始的null值。如图5是他们的比较。在图中我们可以看到NULL值下面一个图中没有NULL值,刚好有9行。下图把他们放在一起比较。



图5

下面我们来剖析一下上面的语句到底做了些什么。首先是一个表值函数(select UnitPriceDiscount,Product711,Product747,Product776 from #Temp1) as up1,这个表值函数从透视结果,也就是临时表中,然后针对每一个产品号进行逆透视:unpivot(ProductPrice for ProductID in(Product711,Product747,Product776)) as up2,然后从逆透视结果中选择ProductID ,ProductPrice,从表值函数中选择UnitPriceDiscount。

延伸阅读

一个例子还不足以让我们理解这个语句,下面来看看TechNet中的例子。

SELECT DaysToManufacture, AVG(StandardCost) AS AverageCost FROM Production.Product

GROUP BY DaysToManufacture;

这个语句查出Product表中的制造时间和平均成本,得到如下的结果

图6

如图可以看到没有制造时间为3天的产品,这里留下一个伏笔,在透视之后会出现一个NULL值。下面使用透视语句对它进行行列转换,就是使用0,1,2,3来作为列,使用具体的制造成本作为行数据。语句如下

1 select
2 'AverageCost' as Cost_Sorted_By_Production_Days,
3 [0],[1],[3],[4]
4 from
5 (select DaysToManufacture,StandardCost from Production.Product) as SourceTable
6 pivot
7 (avg(StandardCost) for DaysToManufacture in ([0],[1],[3],[4])) as PivotTable

依旧,首先用一个表值表达式把要透视的列和透视的项选择出来,然后使用透视语句针对每一个项计算平均成本,最后从这个透视结果中选择出结果。
结果如下图7,我们可以看到制造时间为3天的产品没有一个对应的平均成本。

图7

下面这个例子稍微复杂一点。

1 SELECT VendorID,count(PurchaseOrderID) as PurchaseCunt
2 FROM Purchasing.PurchaseOrderHeader group by VendorID

这条语句查询得到每个供应商和他对应的交易号的个数,也就是每个供应商成交的交易次数。如图8列举出部分结果

图8

从图中我们可以看到供应商1共成交51比交易,供应商2共成交51笔交易。如果我们想查出这些交易分别是和那些雇员成交的应该怎么写呢?首先我们来看看表中全部的雇员情况。

select distinct(EmployeeID) from Purchasing.PurchaseOrderHeader

查询结果如图9

图9

如上图我们可以看到共有12个雇员有成交记录。对于这些雇员,如下查询语句

1 SELECT
2 VendorID,
3 [164] AS Emp164,
4 [198] AS Emp198,
5 [223] AS Emp223,
6 [231] AS Emp231,
7 [233] AS Emp233,
8 [238] as Emp238,
9 [241] as Emp241,
10 [244] as Emp244,
11 [261] as Emp261,
12 [264] as Emp264,
13 [266] as Emp266,
14 [274] as Emp274
15 FROM
16 (SELECT PurchaseOrderID,EmployeeID,VendorID
17 FROM Purchasing.PurchaseOrderHeader) p
18 PIVOT
19 (
20 COUNT (PurchaseOrderID)
21 FOR EmployeeID IN
22 ( [164], [198], [223], [231],[233],[238],[241],[244],[261],[264],[266],[274])
23 ) AS pvt
24 ORDER BY pvt.VendorID;

查询结果如下图10

图10

可以 简单地计算一下1+4+3+5+4+4+4+5+5+4+5+6+2刚好等于51,分开来看就是1号供应商分别和164号雇员成交4比记录,和198号雇员成交3比记录等等。

SQL点滴19—T-SQL中的透视和逆透视相关推荐

  1. SQL Server 透视与逆透视转换解析

    本篇文章聊聊T-SQL中对数据进行透视转换 (pivoting).逆透视转换 (unpivoting) 相关技术. 透视转换是把数据从行的状态旋转为列的状态,逆透视转换则是把数据从列的状态旋转为行的状 ...

  2. T-SQL中的透视和逆透视

    透视 今天抽一点时间来看看透视和逆透视语句,简单的说就是行列转换.假设一个销售表中存放着产品号,产品折扣,产品价格三个列,每一种产品号可能有多种折扣,每一种折扣只对应一个产品价格.下面贴出建表语句和插 ...

  3. python数据逆透视_Python数据神器pandas,轻松搞定嵌套表头——透视与逆透视

    发现许多小伙伴入门Python几个月,还是低效率做数据处理.这套课程以形象的示意图,精心安排的案例,循序渐进带你玩转数据处理分析神器--pandas,课程中还有分析案例噢,干货满满! 前言 上一节我们 ...

  4. [Power Query] 数据的透视与逆透视

    在日常工作中,很多源数据表是二维表,虽然易于阅读,但不适合数据分析,往往需要将其转换为一维表,在Power Query中通过逆透视功能就能轻松实现上述功能 数据的透视与逆透视本质上就是用于二维表和一维 ...

  5. Power BI中的透视列和逆透视

    透视列(Pivot)和逆透视列(Unpivot)是在Excel当中就经常使用的一对数据聚合和拆分方法,在Power BI桌面应用中也提供了同样的功能. 透视列操作是将列下所有的N个非重复数据转换成N个 ...

  6. SQL点滴31—SQL语句中@@IDENTITY和@@ROWCOUNT区别

    原文:SQL点滴31-SQL语句中@@IDENTITY和@@ROWCOUNT区别 SQL语句中@@IDENTITY和@@ROWCOUNT区别 在一条 INSERT.SELECT INTO 或大容量复制 ...

  7. SQL点滴12—SQL Server备份还原数据库中的小把戏

    原文:SQL点滴12-SQL Server备份还原数据库中的小把戏 备份数据库时出现一个不太了解的错误 ,错误信息"is formatted to support  1 media fami ...

  8. SQL点滴35—SQL语句中的exists

    原文:SQL点滴35-SQL语句中的exists 比如在Northwind数据库中有一个查询为 SELECT c.CustomerId,CompanyName FROM Customers c WHE ...

  9. Azure SQL Database (19) Stretch Database 概览

    <Windows Azure Platform 系列文章目录>  Azure SQL Database (19) Stretch Database 概览      Azure SQL Da ...

最新文章

  1. python爬虫requests简单案例_Python小例子:一个最简单的爬虫
  2. jQuery学习之一---选择器
  3. 广州大学计算机技术复试c语言试题,广州大学C语言程序设计期末考试试卷含答案...
  4. 35岁了,转去谷歌做人工智能靠谱吗?
  5. 周鸿祎谈李国庆夫妇互撕:大事男人说了算,小事才听女人的
  6. 实用 VSCODE 8类插件安利,提高开发效率
  7. 请假案例_师生沟通案例8|谢谢你,“请假大王”!
  8. 面试大厂回来,我狠补了一把算法和数据结构
  9. paip.提升用户体验-----c++ 实现360浏览器收藏动作星星动画效果
  10. Flash cs4 for mac 序列号。
  11. html图片自动跳转,点击图片跳转链接(html点击图片跳转链接)
  12. SPSS作业-方差分析-双因素分析
  13. 全桥并网逆变器PLECS仿真
  14. android adb 模拟长按,adb 模拟长按电源键
  15. 东野圭吾《解忧杂货店》读后感
  16. oracle v session表,Oracle技术之V$SESSION_LONGOPS超过系统时间
  17. 安卓开发— —仿微信界面(二)
  18. yolov5的anchor详解
  19. 2018CCPC吉林赛区 | 部分题解 (HDU6555 HDU6556 HDU6559 HDU6561)
  20. OpenCV学习~moviepy视频裁剪

热门文章

  1. L2-014 列车调度(队列模拟:set)
  2. jquery实现增删改(伪)-老男孩作业day13
  3. DevExpress v17.2新版亮点—WinForms篇(四)
  4. 扒一扒那些年我们遇到的奇葩代码
  5. 动画-animation
  6. Linux sudo找不到命令:修改sudo的PATH路径
  7. Android下载文件
  8. found.000文件夹的问题
  9. Sql Server设置用户只能查看并访问特定数据库
  10. jq checked 设置问题