新添加的查询:CTE
WITH DirReps (Manager, DirectReports) AS
(
SELECT ManagerID, COUNT(*) AS DirectReports
FROM HumanResources.Employee
GROUP BY ManagerID
)
SELECT AVG(DirectReports) AS [Average Number of Direct Reports]
FROM DirReps
WHERE DirectReports>= 2 ;
GO
Row_number 取得行号,主要运用于排序; 返回bigint
USE AdventureWorks;
GO
WITH OrderedOrders AS
(
SELECT SalesOrderID, OrderDate,
ROW_NUMBER() OVER (order by OrderDate)as RowNumber
FROM Sales.SalesOrderHeader
)
SELECT *
FROM OrderedOrders
WHERE RowNumber between 50 and 60;
RANK ( ) 返回结果集的分区内每行的排名。行的排名是相关行之前的排名数加一
USE AdventureWorks;
GO
SELECT i.ProductID, p.Name, i.LocationID, i.Quantity,
RANK() OVER (PARTITION BY i.LocationID order by i.Quantity) as RANK
FROM Production.ProductInventory i JOIN Production.Product p
ON i.ProductID = p.ProductID
ORDER BY p.Name
GO
使用 APPLY
APPLY 运算符的左操作数和右操作数都是表表达式。这些操作数之间的主要区别是,
right_table_source 可以使用表值函数,从 left_table_source 获取一个列作为函数的参数之一。
left_table_source 可以包括表值函数,但不能以来自 right_table_source 的列作为参数
使用 APPLY
以下示例假定数据库中存在具有如下架构的以下表:
Departments: DeptID, DivisionID, DeptName, DeptMgrID
EmpMgr: MgrID, EmpID
Employees: EmpID, EmpLastName, EmpFirstName, EmpSalary
inner join区别在不能以来自 left_table_source 的列作为参数
还有一个表值函数(GetReports(MgrID))可以返回指定的 MgrID 直接或间接领导的所有员工的列表(EmpID、EmpLastName、EmpSalary)。
该示例使用 APPLY 返回所有部门和部门中的所有员工。如果某个部门没有任何员工,则不返回该部门的任何行。
SELECT DeptID, DeptName, DeptMgrID, EmpID, EmpLastName, EmpSalary
FROM Departments d CROSS APPLY dbo.GetReports(d.DeptMgrID) ;
相当于
SELECT DeptID, DeptName, DeptMgrID, EmpID, EmpLastName, EmpSalary
FROM Departments d inner join dbo.GetReports() e on d.DeptMgrID=e.mgrid
如果您希望查询为那些没有员工的部门生成行(为 EmpID、EmpLastName 和 EmpSalary 列生成空值),请使用 OUTER APPLY。
SELECT DeptID, DeptName, DeptMgrID, EmpID, EmpLastName, EmpSalary
FROM Departments d OUTER APPLY dbo.GetReports(d.DeptMgrID) ;
使用 PIVOT 和 UNPIVOT
USE AdventureWorks;
GO
SELECT VendorID, [164] AS Emp1, [198] AS Emp2, [223] AS Emp3, [231] AS Emp4, [233] AS Emp5
FROM
(SELECT PurchaseOrderID, EmployeeID, VendorID
FROM Purchasing.PurchaseOrderHeader) p
PIVOT
(
COUNT (PurchaseOrderID)
FOR EmployeeID IN
([164], [198], [223], [231], [233])
) AS pvt
ORDER BY VendorID
以下为部分结果集:
VendorID Emp1 Emp2 Emp3 Emp4 Emp5
1 4 3 5 4 4
2 4 1 5 5 5
3 4 3 5 4 4
4 4 2 5 5 4
5 5 1 5 5 5
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
以下为部分结果集:
VendorID Employee Orders
1 Emp1 4
1 Emp2 3
1 Emp3 5
1 Emp4 4
SQL Server 2005:数据类型最大值varchar(max)
交集函数:
SELECT * FROM A INTERSECT SELECT * FROM B
go
CREATE function uf_splitstring
(
@str varchar(8000) --要分拆的字符串
,@spli varchar(10) --字符串分隔符
)
returns @retab table(istr varchar(8000))
as
begin
declare @i int
declare @splen int
select @splen=len(@spli),@i=charindex(@spli,@str)
while @i > 0
begin
insert into @retab
values(left(@str,@i-1))
select @str=substring(@str,@i+@splen,8000)
select @i=charindex(@spli,@str)
end
if @str<>'' insert into @retab values(@str)
return
end
GO
if exists(select 1 from uf_splitstring('001,002,003',',')t,uf_splitstring('002,004',',')t1 where t.istr=t1.istr)
print '1'
else
print '0'
例子:
DECLARE @T TABLE(ID INT,ParentId INT,Rank INT,StartDate DATETIME)
INSERT INTO @T SELECT 1,0,0,'2006-5-1'
UNION ALL SELECT 2,1,1,'2006-5-2'
UNION ALL SELECT 3,1,1,'2006-5-3'
UNION ALL SELECT 4,2,2,'2006-5-4'
UNION ALL SELECT 5,4,3,'2006-5-5'
UNION ALL SELECT 6,3,2,'2006-5-4';
DECLARE @TIME DATETIME
SET @TIME='2006-5-4';
WITH CTE_T(Id,ParentId,Rank,StartDate)
AS
(
SELECT Id,ParentId,Rank,StartDate
FROM @T
WHERE StartDate=@TIME
UNION ALL
SELECT A.Id,A.ParentId,A.Rank,A.StartDate
FROM @T A, CTE_T B
WHERE A.ID=B.ParentId
)
SELECT DISTINCT *,Tag=CASE WHEN StartDate>=@TIME THEN 1 ELSE 0 END
FROM CTE_T
go
---显示所有下级
WITH CTE_T(menuId,menuname)
AS
(
SELECT menuid,menuname
FROM _sysmenu
WHERE parentmenu=0
UNION all
SELECT A.menuId,A.menuname
FROM _sysmenu A,CTE_T B
WHERE A.parentmenu=B.menuId
)
SELECT * FROM CTE_T
go
---显示所有上级
WITH CTE_T(parentmenu,menuname)
AS
(
SELECT parentmenu,menuname
FROM _sysmenu
WHERE menuid=2095
UNION all
SELECT A.parentmenu,A.menuname
FROM _sysmenu A,CTE_T B
WHERE A.menuid=B.parentmenu
)
SELECT * FROM CTE_T
go
例子2.
create table table1(name varchar(10),course varchar(20),grade int)
insert into table1(name,course,grade) select 'lying','maths','100'
union
select 'lying2','english','200'
union
select 'lying1','chinese','50'
go
Declare @cols nvarchar(max);
WITH CTECourse(Course)
As
(
Select Distinct Course From table1
)
Select @cols = IsNull(@cols + ',[','[') + Course + ']' From CTECourse
DECLARE @sql AS nvarchar(MAX)
SET @sql = N'SELECT *
FROM (SELECT [Name], [Course], [Grade]
FROM table1) as Header
PIVOT(SUM([Grade]) FOR [Course] IN(' + @cols + N')) AS Piv'
PRINT @sql -- for debugging
EXEC sp_executesql @sql
go
drop table table1