T-SQL Enhancement in SQL Server 2005[下篇]
2007-08-24 23:16
555 查看
在第一部分中,我们讨论了APPLY和CTE这两个T-SQL Enhancement。APPLY实现了Table和TVF的Join,CTE通过创建“临时的View”的方式使问题化繁为简。现在我们接着来讨论另外两个重要的T-SQL Enhancement Items:PIVOT和Ranking。
三、 PIVOT Operator
PIVOT的中文意思是“在枢轴上转动”,比如对于一个2维坐标,将横坐标变成纵坐标,将纵坐标变成横坐标。反映在一个Relational Table上的意思就是:变成为列,变列为行。相信大家在进行报表设计的时候都遇到过类似于这样的需求:统计2002年内某个销售人员第一季度每个月处理的订单数。在AdventureWorks Sample Databse中,Sales Order存储于SaleOrderHeader这张表中,它的结果如下:
SELECT SalesPersonID,
SUM(CASE DATEPART(MM,OrderDate)WHEN 1 THEN 1 ELSE 0 END) AS JAN,
SUM(CASE DATEPART(MM,OrderDate)WHEN 2 THEN 1 ELSE 0 END) AS FEB,
SUM(CASE DATEPART(MM,OrderDate)WHEN 3 THEN 1 ELSE 0 END) AS MAR,
SUM(CASE DATEPART(MM,OrderDate)WHEN 4 THEN 1 ELSE 0 END) AS APR
FROM Sales.SalesOrderHeader
WHERE DATEPART(yyyy,OrderDate) = 2002
GROUP BY SalesPersonID
于是我们得到了这样的统计数据:
SELECT SalesPersonID, [1] AS JAN,[2] AS FEB, [3] AS MAR, [4] AS APR
FROM
(
SELECT SalesPersonID, DATEPART(MM,OrderDate) AS MON FROM Sales.SalesOrderHeader WHERE DATEPART(yyyy,OrderDate) = 2002) S
PIVOT ( COUNT(MON) FOR MON IN ([1],[2],[3],[4]) )AS P
在上面的例子中,同过下面的SELECT语句筛选出来的是为经过PIVOT的数据。
通过下面的PIVOT(COUNT(MON)是我们需要统计的数据,FOR MON IN ([1],[2],[3],[4]是统计的范围)就成了我们最终输出的结构了。
如果你第一次见到PIVOT,可以不能一下明白它的实现,但是只要你是使用了一两次,相信就会很容易地掌握它。与PIVOT对应的还以一个操作符UNPIVOT,它完成PIVOT的逆操作,在这里就不介绍了,如果有兴趣的话,可以参考SQL Server Books Online。
四、 Ranking
排序与排名是我们最为常用的统计方式,比如对班级的学生根据成员进行排名,或者按照成绩高低把学生划分成若干梯队:比如最好成绩的10名学生属于第一梯队,后10名又划分为第二梯队,以此类推。Ranking设计的Key Words包括:ROW_NUMBER(),RANK(),DENSE_RANK(),NTILE()。我们现在就来介绍一下他们的用法和相互之间的差异。
1. 1. ROW_NUMBER()
看到ROW_NUMBER(),我想绝大多数人会像想到Oracle的ROWNUM。他们的作用相似,都是表示某条记录所处的Index。ROW_NUMBER()比Oracle的ROWNUM更加强大的是,它可以通过OVER语句指定一个进行排序的Column,比如:ROW_NUMBER() OVER (ORDER BY CustomerID)。
我们来看一个例子:对Sales.SalesOrderHeader按照CustomerID进行排序,并显示每条记录的Row Number。
下面是查询结果:
SELECT SalesOrderID,CustomerID,ROW_NUMBER() OVER (ORDER BY CustomerID) AS RowNum FROM Sales.SalesOrderHeaderORDER BY SalesOrderID
查询获得的结果是:
SELECT CustomerID,COUNT(*) AS OrderCount,ROW_NUMBER() OVER (ORDER BY OrderCount)
FROM Sales.SalesOrderHeader
GROUP BY CustomerID
要是想按照OrderCount,可以使用第一部分介绍的CTE:
2. RANK()
RANK()的使用和ROW_NUMBER()类似。不过它与ROW_NUMBER()所不同的是:对于被指定为排序的字段,具有相同值得Row对应的返回值相同。比如:
下面是相应的查询结果:
SELECT SalesOrderID,CustomerID,DENSE_RANK() OVER (ORDER BY CustomerID) AS RowNum
FROM Sales.SalesOrderHeader
就来产生如下的查询结果:
SELECT SalesOrderID,CustomerID,NTILE(3) OVER (ORDER BY CustomerID) AS RowNum
FROM Sales.SalesOrderHeader
WHERE CustomerID <3
其查询结果为:
SELECT SalesOrderID,CustomerID,RANK() OVER (PARTITION BY CustomerID ORDER BY OrderDate) AS RowNum
FROM Sales.SalesOrderHeader
相应的查询结果:
T-SQL Enhancement in SQL Server 2005:
[原创]T-SQL Enhancement in SQL Server 2005 - Part I
[原创]T-SQL Enhancement in SQL Server 2005 - Part II
Reference: 《Programming Microsoft SQL Server 2005》 By Andrew J. Brust & Stephen Forte
三、 PIVOT Operator
PIVOT的中文意思是“在枢轴上转动”,比如对于一个2维坐标,将横坐标变成纵坐标,将纵坐标变成横坐标。反映在一个Relational Table上的意思就是:变成为列,变列为行。相信大家在进行报表设计的时候都遇到过类似于这样的需求:统计2002年内某个销售人员第一季度每个月处理的订单数。在AdventureWorks Sample Databse中,Sales Order存储于SaleOrderHeader这张表中,它的结果如下:
SELECT SalesPersonID,
SUM(CASE DATEPART(MM,OrderDate)WHEN 1 THEN 1 ELSE 0 END) AS JAN,
SUM(CASE DATEPART(MM,OrderDate)WHEN 2 THEN 1 ELSE 0 END) AS FEB,
SUM(CASE DATEPART(MM,OrderDate)WHEN 3 THEN 1 ELSE 0 END) AS MAR,
SUM(CASE DATEPART(MM,OrderDate)WHEN 4 THEN 1 ELSE 0 END) AS APR
FROM Sales.SalesOrderHeader
WHERE DATEPART(yyyy,OrderDate) = 2002
GROUP BY SalesPersonID
于是我们得到了这样的统计数据:
SELECT SalesPersonID, [1] AS JAN,[2] AS FEB, [3] AS MAR, [4] AS APR
FROM
(
SELECT SalesPersonID, DATEPART(MM,OrderDate) AS MON FROM Sales.SalesOrderHeader WHERE DATEPART(yyyy,OrderDate) = 2002) S
PIVOT ( COUNT(MON) FOR MON IN ([1],[2],[3],[4]) )AS P
在上面的例子中,同过下面的SELECT语句筛选出来的是为经过PIVOT的数据。
SELECT SalesPersonID, DATEPART(MM,OrderDate) AS MON FROM Sales.SalesOrderHeader WHERE DATEPART(yyyy,OrderDate) = 2002
通过下面的PIVOT(COUNT(MON)是我们需要统计的数据,FOR MON IN ([1],[2],[3],[4]是统计的范围)就成了我们最终输出的结构了。
PIVOT ( COUNT(MON) FOR MON IN ([1],[2],[3],[4]) )
如果你第一次见到PIVOT,可以不能一下明白它的实现,但是只要你是使用了一两次,相信就会很容易地掌握它。与PIVOT对应的还以一个操作符UNPIVOT,它完成PIVOT的逆操作,在这里就不介绍了,如果有兴趣的话,可以参考SQL Server Books Online。
四、 Ranking
排序与排名是我们最为常用的统计方式,比如对班级的学生根据成员进行排名,或者按照成绩高低把学生划分成若干梯队:比如最好成绩的10名学生属于第一梯队,后10名又划分为第二梯队,以此类推。Ranking设计的Key Words包括:ROW_NUMBER(),RANK(),DENSE_RANK(),NTILE()。我们现在就来介绍一下他们的用法和相互之间的差异。
1. 1. ROW_NUMBER()
看到ROW_NUMBER(),我想绝大多数人会像想到Oracle的ROWNUM。他们的作用相似,都是表示某条记录所处的Index。ROW_NUMBER()比Oracle的ROWNUM更加强大的是,它可以通过OVER语句指定一个进行排序的Column,比如:ROW_NUMBER() OVER (ORDER BY CustomerID)。
我们来看一个例子:对Sales.SalesOrderHeader按照CustomerID进行排序,并显示每条记录的Row Number。
SELECT SalesOrderID,CustomerID,ROW_NUMBER() OVER (ORDER BY CustomerID) AS RowNum FROM Sales.SalesOrderHeader
下面是查询结果:
SELECT SalesOrderID,CustomerID,ROW_NUMBER() OVER (ORDER BY CustomerID) AS RowNum FROM Sales.SalesOrderHeaderORDER BY SalesOrderID
查询获得的结果是:
SELECT CustomerID,COUNT(*) AS OrderCount,ROW_NUMBER() OVER (ORDER BY OrderCount)
FROM Sales.SalesOrderHeader
GROUP BY CustomerID
要是想按照OrderCount,可以使用第一部分介绍的CTE:
WITH CTE_Order(CustomerID,OrderCount) AS ( SELECT CustomerID,COUNT(*) AS OrderCount FROM Sales.SalesOrderHeader GROUP BY CustomerID ) SELECT CustomerID,OrderCount,ROW_NUMBER() OVER (ORDER BY OrderCount) FROM CTE_Order
2. RANK()
RANK()的使用和ROW_NUMBER()类似。不过它与ROW_NUMBER()所不同的是:对于被指定为排序的字段,具有相同值得Row对应的返回值相同。比如:
SELECT SalesOrderID,CustomerID,RANK() OVER (ORDER BY CustomerID) AS RowNum FROM Sales.SalesOrderHeader
下面是相应的查询结果:
SELECT SalesOrderID,CustomerID,DENSE_RANK() OVER (ORDER BY CustomerID) AS RowNum
FROM Sales.SalesOrderHeader
就来产生如下的查询结果:
SELECT SalesOrderID,CustomerID,NTILE(3) OVER (ORDER BY CustomerID) AS RowNum
FROM Sales.SalesOrderHeader
WHERE CustomerID <3
其查询结果为:
SELECT SalesOrderID,CustomerID,RANK() OVER (PARTITION BY CustomerID ORDER BY OrderDate) AS RowNum
FROM Sales.SalesOrderHeader
相应的查询结果:
T-SQL Enhancement in SQL Server 2005:
[原创]T-SQL Enhancement in SQL Server 2005 - Part I
[原创]T-SQL Enhancement in SQL Server 2005 - Part II
Reference: 《Programming Microsoft SQL Server 2005》 By Andrew J. Brust & Stephen Forte
相关文章推荐
- T-SQL Enhancement in SQL Server 2005[下篇]
- [原创]T-SQL Enhancement in SQL Server 2005 - Part I
- T-SQL Enhancement in SQL Server 2005[上篇]
- T-SQL Enhancement in SQL Server 2005[上篇]
- XML Enhancement in SQL Server 2005
- [原创]T-SQL Enhancement in SQL Server 2005 - Part II
- Troubleshooting Performance Problems in SQL Server 2005
- How to Implement an Automatic Sliding Window in a Partitioned Table on SQL Server 2005
- Copy a table from one database to another in SQL Server 2005
- Working with schemas in SQL Server 2005(zz)
- TFS Project error in SQL Server 2005 after installing SQL Server 2008
- MCITP SQL Server 2005 Database Developer All-in-One Exam Guide
- Generate a unique number in Sql Server 2005
- bookmark: partitioned tables in sql server 2005
- Problem in connecting VS 2005 to SQL Server 2008
- Partitioned Tables and Indexes in SQL Server 2005
- [翻译-收藏] Batch Compilation, Recompilation, and Plan Caching Issues in SQL Server 2005
- Partitioned Tables and Indexes in SQL Server 2005 (EN原版)
- Missing Indexes in SQL Server 2005
- How to Alter a Replicated Article in SQL Server 2005