set nocount on
--> 测试数据:[ta]
if object_id('[ta]') is not null drop table [ta]
go
create table [ta]([id] int,[name] varchar(1))
insert [ta]
select 1,'a'union all
select 2,'b'union all
select 3,'c'union all
select 4,'d'
--> 测试数据:[tb]
if object_id('[tb]') is not null drop table [tb]
go
create table [tb]([id] int,[name] varchar(2))
insert [tb]
select 1,'ff'union all
select 1,'yy'union all
select 1,'yf'union all
select 2,'xx'union all
select 2,'oo'union all
select 3,'xo'union all
select 5,'fy'
--------------开始查询--------------------------
--SQL 2005 新的表运算符apply pivot unpivot
--apply 涉及到下面两个步骤的子集(取决于apply 的类型)
--1、把右表表达式应用到左表输入的行
--2、添加外部行
--使用apply时,就好像先计算左输入,然后为左输入中的每一行计算一次右输入。
--cross apply 和outer apply的区别在于前者的外部(左侧)在内部(右侧)
--找不到对应航的时候不返回,后者则返回null
--看下面的例子
select * from[ta] a cross apply(select * from tb b where a.[id]=b.[id] )c
select * from[ta] a outer apply(select * from tb b where a.[id]=b.[id] )c
--cross apply 很重要的一个应用就是可以用来返回前N行
select c.*from [ta] a cross apply(select top 2 * from tb b where a.[id]=b.[id] order by b.name )c
--pivot 包含下面三个逻辑
--1、隐式分组
--2、隔离值
--3、聚合函数
select * fromtb pivot(count(id) for [id] in([1],[2],[3])) as p
--unpivot
--UNPIVOT 与PIVOT 执行相反的操作,将表值表达式的列转换为列值。
--UNPIVOT 将与PIVOT 执行几乎完全相反的操作,将列转换为行。
--假设以上示例中生成的表在数据库中存储为pvt,
--并且您需要将列标识符Emp1、Emp2、Emp3、Emp4 和Emp5 旋转为对应于特定供应商的行值。
--这意味着必须标识另外两个列。包含要旋转的列值(Emp1、Emp2...)的列将被称为Employee,
--将保存当前位于待旋转列下的值的列被称为Orders。这些列分别对应于
-- Transact-SQL 定义中的pivot_column 和value_column。以下为该查询。
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
--select * from pvt
--Unpivot the table.
SELECT VendorID, Employee, Orders
FROM pvt
UNPIVOT(
Orders FOR Employee IN(Emp1, Emp2, Emp3, Emp4, Emp5)
)AS unpvt
GO
--请注意,UNPIVOT 并不完全是PIVOT 的逆操作。PIVOT 会执行一次聚合,
--从而将多个可能的行合并为输出中的单个行。
--而UNPIVOT 不会重现原始表值表达式的结果,因为行已经被合并了。
--另外,UNPIVOT 的输入中的空值不会显示在输出中,
--而在执行PIVOT 操作之前,输入中可能有原始的空值。
--PIVOT 和UNPIVOT 在语法上可能让人很难理解,不过用得多了就熟悉了也就理解了