关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » SQL语言 »SQL经典:T-SQL中的透视和逆透视解析(1)

    SQL经典:T-SQL中的透视和逆透视解析(1)

    2011-07-08 13:40:00 出处:ITJS
    分享

    SQL查询时,我们可能会用到T-SQL透视和逆透视的功能,比如我们对销售表中的列进行查询时就用到了。透视运算符要使用子查询中的数据进行聚合运算,然后再输出。本文通过实例详细讲述了这一过程,下面先说透视。

    透视

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

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

    首先来看一条查询语句

    select ProductID,UnitPriceDiscount,SUM(ProductPrice) as SumPrice    from SalesOrderDetail    group by ProductID,UnitPriceDiscount   order by ProductID,UnitPriceDiscount 

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

    SQL点滴:T-SQL中的透视和逆透视解析

    图1

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

    SQL点滴:T-SQL中的透视和逆透视解析

    图2

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

    select * from    (select sod.ProductPrice,sod.ProductID,sod.UnitPriceDiscount from SalesOrderDetail sod) so   pivot   (   sum(so.ProductPrice) for so.ProductID in([711],[747],[776])   6 ) as pt   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,使用这个结果集生成我们需要的输出。假如想要得到一个更加合适的列名可以修改筛选条件。如下:

    select pt.UnitPriceDiscount,[711] as Product711,[747] as Product747,[776] as Product747 from   (select sod.ProductPrice,sod.ProductID,sod.UnitPriceDiscount from SalesOrderDetail sod) so   pivot   (   sum(so.ProductPrice) for so.ProductID in([711],[747],[776])   ) as pt   order by UnitPriceDiscount 

    输出的结果如下图3

    SQL点滴:T-SQL中的透视和逆透视解析

    图3

    逆透视

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

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

    查询结果如下图4:

    SQL点滴:T-SQL中的透视和逆透视解析

    图4

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

    SQL点滴:T-SQL中的透视和逆透视解析

    图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表中的制造时间和平均成本,得到如下的结果

    SQL点滴:T-SQL中的透视和逆透视解析

    图6

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

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

    依旧,首先用一个表值表达式把要透视的列和透视的项选择出来,然后使用透视语句针对每一个项计算平均成本,最后从这个透视结果中选择出结果。

    结果如下图7,我们可以看到制造时间为3天的产品没有一个对应的平均成本。

    SQL点滴:T-SQL中的透视和逆透视解析

    图7

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

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

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

    SQL点滴:T-SQL中的透视和逆透视解析

    图8

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

    select distinct(EmployeeID) from Purchasing.PurchaseOrderHeader 

    查询结果如图9

    SQL点滴:T-SQL中的透视和逆透视解析

    图9

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

    SELECT    VendorID,   [164] AS Emp164,   [198] AS Emp198,   [223] AS Emp223,   [231] AS Emp231,   [233] AS Emp233,   [238] as Emp238,   [241] as Emp241,   [244] as Emp244,   [261] as Emp261,   [264] as Emp264,   [266] as Emp266,   [274] as Emp274   15 FROM    (SELECT PurchaseOrderID,EmployeeID,VendorID   FROM Purchasing.PurchaseOrderHeader) p   PIVOT   (   COUNT (PurchaseOrderID)   FOR EmployeeID IN   ( [164], [198], [223], [231],[233],[238],[241],[244],[261],[264],[266],[274])   ) AS pvt   24 ORDER BY pvt.VendorID; 

    查询结果如下图10

    SQL点滴:T-SQL中的透视和逆透视解析

    图10

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

    关于透视和逆透视的知识就介绍到这里,谢谢大家!

    SQL查询时,我们可能会用到T-SQL透视和逆透视的功能,比如我们对销售表中的列进行查询时就用到了。透视运算符要使用子查询中的数据进行聚合运算,然后再输出。本文通过实例详细讲述了这一过程,下面先说透视。

    透视

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

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

    首先来看一条查询语句

    select ProductID,UnitPriceDiscount,SUM(ProductPrice) as SumPrice    from SalesOrderDetail    group by ProductID,UnitPriceDiscount   order by ProductID,UnitPriceDiscount 

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

    SQL点滴:T-SQL中的透视和逆透视解析

    图1

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

    SQL点滴:T-SQL中的透视和逆透视解析

    图2

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

    select * from    (select sod.ProductPrice,sod.ProductID,sod.UnitPriceDiscount from SalesOrderDetail sod) so   pivot   (   sum(so.ProductPrice) for so.ProductID in([711],[747],[776])   6 ) as pt   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,使用这个结果集生成我们需要的输出。假如想要得到一个更加合适的列名可以修改筛选条件。如下:

    select pt.UnitPriceDiscount,[711] as Product711,[747] as Product747,[776] as Product747 from   (select sod.ProductPrice,sod.ProductID,sod.UnitPriceDiscount from SalesOrderDetail sod) so   pivot   (   sum(so.ProductPrice) for so.ProductID in([711],[747],[776])   ) as pt   order by UnitPriceDiscount 

    输出的结果如下图3

    SQL点滴:T-SQL中的透视和逆透视解析

    图3

    逆透视

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

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

    查询结果如下图4:

    SQL点滴:T-SQL中的透视和逆透视解析

    图4

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

    SQL点滴:T-SQL中的透视和逆透视解析

    图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表中的制造时间和平均成本,得到如下的结果

    SQL点滴:T-SQL中的透视和逆透视解析

    图6

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

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

    依旧,首先用一个表值表达式把要透视的列和透视的项选择出来,然后使用透视语句针对每一个项计算平均成本,最后从这个透视结果中选择出结果。

    结果如下图7,我们可以看到制造时间为3天的产品没有一个对应的平均成本。

    SQL点滴:T-SQL中的透视和逆透视解析

    图7

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

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

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

    SQL点滴:T-SQL中的透视和逆透视解析

    图8

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

    select distinct(EmployeeID) from Purchasing.PurchaseOrderHeader 

    查询结果如图9

    SQL点滴:T-SQL中的透视和逆透视解析

    图9

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

    SELECT    VendorID,   [164] AS Emp164,   [198] AS Emp198,   [223] AS Emp223,   [231] AS Emp231,   [233] AS Emp233,   [238] as Emp238,   [241] as Emp241,   [244] as Emp244,   [261] as Emp261,   [264] as Emp264,   [266] as Emp266,   [274] as Emp274   15 FROM    (SELECT PurchaseOrderID,EmployeeID,VendorID   FROM Purchasing.PurchaseOrderHeader) p   PIVOT   (   COUNT (PurchaseOrderID)   FOR EmployeeID IN   ( [164], [198], [223], [231],[233],[238],[241],[244],[261],[264],[266],[274])   ) AS pvt   24 ORDER BY pvt.VendorID; 

    查询结果如下图10

    SQL点滴:T-SQL中的透视和逆透视解析

    图10

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

    关于透视和逆透视的知识就介绍到这里,谢谢大家!

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    正版 Windows 11产品密钥怎么查找/查看?

    还有3个月,微软将停止 Windows 10 的更新

    Windows 10 终止支持后,企业为何要立即升级?

    Windows 10 将于 2025年10 月终止技术支持,建议迁移到 Windows 11

    Windows 12 发布推迟,微软正全力筹备Windows 11 25H2更新

    Linux 退出 mail的命令是什么

    Linux 提醒 No space left on device,但我的空间看起来还有不少空余呢

    hiberfil.sys文件可以删除吗?了解该文件并手把手教你删除C盘的hiberfil.sys文件

    Window 10和 Windows 11哪个好?答案是:看你自己的需求

    盗版软件成公司里的“隐形炸弹”?老板们的“法务噩梦” 有救了!

    IT头条

    公安部:我国在售汽车搭载的“智驾”系统都不具备“自动驾驶”功能

    02:03

    液冷服务器概念股走强,博汇、润泽等液冷概念股票大涨

    01:17

    亚太地区的 AI 驱动型医疗保健:2025 年及以后的下一步是什么?

    16:30

    智能手机市场风云:iPhone领跑销量榜,华为缺席引争议

    15:43

    大数据算法和“老师傅”经验叠加 智慧化收储粮食尽显“科技范”

    15:17

    技术热点

    SQL汉字转换为拼音的函数

    windows 7系统无法运行Photoshop CS3的解决方法

    巧用MySQL加密函数对Web网站敏感数据进行保护

    MySQL基础知识简介

    Windows7和WinXP下如何实现不输密码自动登录系统的设置方法介绍

    windows 7系统ip地址冲突怎么办?windows 7系统IP地址冲突问题的

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。