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比记录等等。
来源:http://www.cnblogs.com/tylerdonet/archive/2011/07/07/2100313.html
T-SQL中的透视和逆透视的更多相关文章
- SQL点滴19—T-SQL中的透视和逆透视
原文:SQL点滴19-T-SQL中的透视和逆透视 透视 今天抽一点时间来看看透视和逆透视语句,简单的说就是行列转换.假设一个销售表中存放着产品号,产品折扣,产品价格三个列,每一种产品号可能有多种折扣, ...
- SQL SERVER技术内幕之7 透视与逆透视
1.透视转换 透视数据(pivoting)是一种把数据从行的状态旋转为列的状态的处理,在这个过程中可能须要对值进行聚合. 每个透视转换将涉及三个逻辑处理阶段,每个阶段都有相关的元素:分组阶段处理相关的 ...
- T-SQL——数据透视和逆透视
目录 0. 测试数据集及说明 0.1 准备测试数据 0.2 对一维表和二维表理解 1. 透视转换 1.1 使用标准SQL进行数据透视 1.2 使用T-SQL中pivot函数进行数据透视 1.3 关于 ...
- T-SQL基础(7) - 透视,逆透视和分组集
透视转换: use tempdb;if object_id('dbo.Orders', 'U') is not null drop table dbo.Orders;create table dbo. ...
- 《BI那点儿事》数据流转换——逆透视转换
逆透视转换将来自单个记录中多个列的值扩展为单个列中具有同样值的多个记录,使得非规范的数据集成为较规范的版本.例如,每个客户在列出客户名的数据集中各占一行,在该行的各列中显示购买的产品和数量.逆透视转换 ...
- SQL Server进阶(八)查询——开窗函数、四大排名函数、透视数据、逆透视数据
概述 ROW_NUMBER() OVER(PARTITION BY CustId ORDER BY ID DESC) https://www.jb51.net/article/75533.htm 开窗 ...
- PIVOT(透视转换)和UNPIVOT(逆透视转换)
一.原数据状态 二.手动写透视转换1 三.手动写透视转换2 四.PIVOT(透视转换)和UNPIVOT(逆透视转换)详细使用 使用标准SQL进行透视转换和逆视转换 --行列转换 create tabl ...
- UNPIVOT逆透视以及动态逆透视存储过程
前几天一直练习PIVOT透视,还实现了动态透视的存过程<动态透视表>https://www.cnblogs.com/insus/p/10888277.html 今天练习MS SQL Ser ...
- JQuery选择器大全 前端面试送命题:面试题篇 对IOC和DI的通俗理解 c#中关于协变性和逆变性(又叫抗变)帮助理解
JQuery选择器大全 jQuery 的选择器可谓之强大无比,这里简单地总结一下常用的元素查找方法 $("#myELement") 选择id值等于myElement的元素 ...
随机推荐
- 【转】Mac OS X 快捷键(完整篇)
原文网址:http://www.nooidea.com/2011/01/mac-os-x-keyboard-shortcuts.html 没有写到基本的一些组合,只是一些可能大家不太常用到但及其提高机 ...
- SharePoint 2010顶部链接导航栏的详细操作
转:http://www.360sps.com/Item/UseTopLink.aspx 在SharePoint 2010环境的页面中,导航链接总体上可以分为两类,一类是显示在左侧的快速启动栏,另一类 ...
- 组合计数(polya计数):SGU 282 Isomorphism
因为论文的题解写得太好了,直接贴. #include <iostream> #include <cstring> #include <cstdio> using n ...
- .Net 调式案例—实验4 高CPU(High CPU)回顾
原文地址:http://blog.csdn.net/directionofear/article/details/8033506 如果Web应用程序经常遇到的问题按频率排名的话,我觉得 第一名unha ...
- [LeetCode] 42. Trapping Rain Water 解题思路
Given n non-negative integers representing an elevation map where the width of each bar is 1, comput ...
- 天津Uber优步司机奖励政策(2月1日~2月7日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- PC-全国的 DNS服务商
我们请选第2个.然后根据自己的省市来填写..我复制了下版主给的网站 北京:202.96.199.133 202.96.0.133 202.106.0.20 202.106.148.1 202.97.1 ...
- hdoj 1200 To and Fro
To and Fro Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- MongoDB log4j 日志整合
在分布式系统当中,这些服务可能分别部署在不同的服务器上,并且有各自的日志输出.为了方便对这些日志进行统一管理和分析.我们可以将日志统一输出到指定的数据库系统中,而再由日志分析系统去管理.而这个储存日志 ...
- 【Struts2+Spring3+Hibernate3】SSH框架整合实现CRUD_1.2
作者: hzboy192@192.com Blog: http://my.csdn.net/peng_hao1988 版本总览:http://blog.csdn.net/peng_hao1988/ar ...