在前两篇T-SQL查询处理详解, T-SQL查询处理详解 (续)中,我较为详细地介绍了在一般查询中忽略实际的优化执行计划的情况下的逻辑处理过程。接下来,我将从表运算符,连接查询,分析函数,子查询等方面入手,深入地探讨这些细节,欢迎大家一起讨论T-SQL开发中遇到的问题。废话不多说,开始了。
SQL SERVER 2008支持4种表运算符,JOIN,PIVOT,UNPIOVT,APPLY,。这四种运算符,JOIN大家肯定不陌生,但是后面的几个,估计就有不少人很少使用了。
一.PIVOT。
首先看这样的一条SQL查询。

SELECT EmployeeID,
  SUM(CASE WHEN theyear = 2006 THEN themoney END) AS [2006],
  SUM(CASE WHEN theyear = 2007 THEN themoney END) AS [2007],
  SUM(CASE WHEN theyear = 2008 THEN themoney END) AS [2008],
  SUM(CASE WHEN theyear = 2009 THEN themoney END) AS [2009],
  SUM(CASE WHEN theyear = 2010 THEN themoney END) AS [2010],
  SUM(CASE WHEN theyear = 2011 THEN themoney END) AS [2011]
FROM (SELECT EmployeeID, YEAR(Orderdate) AS theyear, themoney
      FROM dbo.Order) AS O
GROUP BY EmployeeID;
这种行转列的需求,在实际情况中特别常见,尤其是在提取年度或者月度报表的数据时,基本少不了这种结果集。看看上面的这条查询,是不是觉得不是很好。不好在哪里呢?有两点,1.代码量大,而且重复代码太多,碰到很多行要转成列的情况,就非常麻烦了。在项目里,经常碰到做月度报表,需要把12个月的数据利用这种写法转成列,就让人吐血了;2.执行效率不高。
这时,我向您介绍T-SQL中特有的表运算符,PIVOT。Pivot运算符用于在列和行之间对数据进行旋转或透视转换,同时执行聚合运算。对于上面的需求,用PIVOT可以如下实现相同的功能:
SELECT * FROM (SELECT EmployeeID, YEAR(Orderdate) AS theyear, themoney
      FROM dbo.Order) AS O
  PIVOT(SUM(themoney) FOR theyear IN([2006],[2007],[2008],[2009],[2010],[2011])) AS P;
怎么样,是不是简洁多了?
来简要分析一下PIVOT的执行过程。PIVOT运算符用一个名为O的表表达式作为它的左输入,每个订单占一行,包含EmployeeID和theyear和themoney。
PIVOT操作涉及到一下三个逻辑阶段。
1.分组。来看看PIVOT子句,我们发现,PIVOT运算符引用了表O(给表取的别名)的两个列作为输入参数,分别是themoney和theyear。在这个阶段,会隐式对表O中的行进行分组,分组依据是根据那些没有作为pivot输入参数的所有列。所以,就相当于有一个隐藏的group by EmployeeID一样,最后结果集就是每个EmployeeID作为一个组。
2.扩展。这个阶段是把原始列的值扩展到他们相应的目标列中,在逻辑上,相当于为IN子句中指定的每个目标列使用以下case表达式:
CASE WHEN <spreading_col> = <target_col_element> THEN  <expression> END.
注意一点,不带ELSE的CASE子句相当于包含了一个隐式的ELSE NULL。
3.聚合。这个阶段就是对每个CASE表达式应用指定的聚合函数,对于上边的查询,就是SUM(),并生成结果列。
对于PIVOT的更多的应用,有机会再深入了解。
二.UNPIVOT。
很明显,UN这个前缀表明了,它做的操作是跟PIVOT相反的,即列转行。UNPIVOT操作涉及到以下三个逻辑处理阶段。
1,生成副本
2,提取元素
3,删除带有NULL的行
看看这个MSDN上的例子。
CREATE TABLE pvt (VendorID int, Emp1 int, Emp2 int,
    Emp3 int, Emp4 int, Emp5 int);
GO
INSERT INTO pvt VALUES (1,4,3,5,4,4);
INSERT INTO pvt VALUES (2,4,1,5,5,5);
INSERT INTO pvt VALUES (3,4,3,5,4,4);
INSERT INTO pvt VALUES (4,4,2,5,5,4);
INSERT INTO pvt VALUES (5,5,1,5,5,5);
GO
--Unpivot the table.
SELECT VendorID, Employee, Orders
FROM
   (SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5
   FROM pvt) p
UNPIVOT
   (Orders FOR Employee IN
      (Emp1, Emp2, Emp3, Emp4, Emp5)
)AS unpvt;
GO
简单对上边的查询作一个分析。UNPIVOT的输入是左表表达式P,第一步,先为P中的行生成多个副本,在UNPIVOT中出现的每一列,都会生成一个副本。因为这里的IN子句有5个列名称,所以要为每个来源行生成5个副本。结果得到的虚拟表中将新增一个列,用来以字符串格式保存来源列的名称(for和IN之间的,上面例子是Employee )。第二步,根据新增的那一列中的值从来源列中提取出与列名对应的行。第三步,删除掉结果列值为null的行,完成这个查询。
三.APPLY。
APPLY运算符是把右表表达式应用与左输入中的每一行。对于左表中的每一行,都要计算一次右边输入的表达式。
APPLY 有两种形式:CROSS APPLY 和 OUTER APPLY。CROSS APPLY 仅返回外部表中通过右表表达式生成结果集的行。OUTER
APPLY 既返回生成结果集的行,也返回不生成结果集的行,其中右表表达式生成的列中的值为 NULL。(外部表:左边表,内部表:右表表达式)
以下示例查询为每个客户返回具有最大订单ID的两个订单:
SELECT C.customerid, C.city, A.orderid
FROM dbo.Customers AS C
  CROSS APPLY
    (SELECT TOP (2) O.orderid, O.customerid
     FROM dbo.Orders AS O
     WHERE O.customerid = C.customerid
     ORDER BY orderid DESC) AS A;
如果将CROSS APPLY换成了OUTER APPLY,则会把不满足右表表达式的行添加进来,并给内部表的列设为NULL。
欢迎大家一起探讨T-SQL开发,并提出问题,一起讨论。
参考文献:《Microsoft SQL Server 2008 技术内幕:T-SQL查询》

转载于:https://www.cnblogs.com/JimmyGe/archive/2011/03/11/1981880.html

T-SQL逻辑处理之表运算符相关推荐

  1. SQL Server:APPLY表运算符

    SQL Server 2005(含)以上版本,新增了APPLY表运算,为我们日常查询带来了极大的方便. 新增的APPLY表运算符把右表表达式应用到左表表达式中的每一行.它不像JOIN那样先计算那个表表 ...

  2. oracle表结构修改回滚,87.Oracle数据库SQL开发之 修改表内存——数据库事务的提交和回滚...

    87.Oracle数据库SQL开发之 修改表内存--数据库事务的提交和回滚 数据库事务(transaction)就是一组SQL语句,这组SQL语句时一个逻辑工作单元. 要永久性的记录事务中SQL语句的 ...

  3. MySQL补充部分-SQL逻辑查询语句执行顺序

    一 SELECT语句关键字的定义顺序 SELECT DISTINCT <select_list> FROM <left_table> <join_type> JOI ...

  4. mysql五补充部分:SQL逻辑查询语句执行顺序

    mysql五补充部分:SQL逻辑查询语句执行顺序一 SELECT语句关键字的定义顺序 二 SELECT语句关键字的执行顺序 三 准备表和数据 四 准备SQL逻辑查询测试语句 五 执行顺序分析 一 SE ...

  5. Sql server 2005系统表详细说明

    sysaltfiles 主数据库 保存数据库的文件  syscharsets 主数据库字符集与排序顺序  sysconfigures 主数据库 配置选项 syscurconfigs 主数据库当前配置选 ...

  6. groovy怎样从sql语句中截取表名_SQL基础教程学习笔记

    点击上方SQL数据库开发,关注获取SQL视频教程 SQL专栏 SQL数据库基础知识汇总 SQL数据库高级知识汇总 1.数据库和SQL RDBMS:关系数据库管理系统 比较代表性的有:Oracle(甲骨 ...

  7. 【数据库实验课堂】实验二 使用SQL Server管理数据表

    实验二 使用SQL Server管理数据表: 1.请在指定数据库内完成以下内容: 1) 依据数据表的结构创建相对应的数据表,表结构如下所示: **学生信息表(student)**字段名称 字段类型及长 ...

  8. 【数据库】第一章 数据库的分类、SQL、数据库、表和表记录的常用操作

    [数据库]第一章 数据库的分类.SQL.数据库与表的常用操作 文章目录 [数据库]第一章 数据库的分类.SQL.数据库与表的常用操作 一.数据库的分类 1.关系型数据库 2.非关系型数据库 3.MyS ...

  9. 学习SQL:SQL Server数据透视表

    In the previous few articles in this series, we've set the foundations on how to create a report. We ...

最新文章

  1. 华为,牵手这所新大学!
  2. 微服务架构下的测试之道
  3. Oracle 数据泵(IMPDP/EXPDP)导入导出总结
  4. 将不确定变为确定~transactionscope何时提升为分布式事务?
  5. 今日arXiv精选 | 14 篇 ICCV 2021 最新论文
  6. SAP 电商云 Spartacus UI 客户端模式下产品主数据的 HTTP 请求设计
  7. Sublime Text 2 入门及技巧
  8. 预训练语言模型真的是世界模型?
  9. java确认rabbitmq_RabbitMQ的消息确认模式
  10. python中的分支语句
  11. Java基础教程:JavaArrays工具类
  12. Package requirements (pthread-stubs xau = 0.99.2) were not met:
  13. java程序无法启动_无法打开java小程序?小迅支招
  14. 光敏传感器实验-传感器原理及应用实验
  15. ubuntu svn命令
  16. 关于如何关闭Windows错误报告
  17. php编网页版计算器,php编程实现简单的网页版计算器功能
  18. 全网疯传!最新高频100题汇总(附答案详解)
  19. 一键检测Linux VPS/服务器配置、IO、国内节点下载测速
  20. Python制作手游《和平精英》游戏资料查询助手

热门文章

  1. 广播 BroadCastReceiver
  2. 用 或 || 取代常规 if - else 结构
  3. [转]关于flash中图片(jpg\png\gif)旋转后锯齿(模糊)问题
  4. Oracle ERP权限管理
  5. linux内核剪裁 4412,itop4412开发板-Linux内核的编译
  6. cube station下载_Cube Station
  7. 2021年NBA附加赛第一轮预测
  8. (31)FPGA面试题系统最高速度计算方法
  9. c#读蓝牙数据_C#读取BWT901CL蓝牙传感器的数据
  10. 为什么叫光呆公式光_光镊力学理论简析