A. 使用简单 FROM 子句
下面的示例从 AdventureWorks 示例数据库中的 SalesTerritory 表中检索 TerritoryID 和 Name 列。
USE AdventureWorks ;
GO
SELECT TerritoryID, Name
FROM Sales.SalesTerritory
ORDER BY TerritoryID ;
下面是结果集:
TerritoryID Name
----------- ------------------------------
1 Northwest
2 Northeast
3 Central
4 Southwest
5 Southeast
6 Canada
7 France
8 Germany
9 Australia
10 United Kingdom
(10 row(s) affected)
B. 使用 TABLOCK 和 HOLDLOCK 优化器提示
下面的部分事务说明了如何在 Employee 上放置一个显式共享表锁,以及如何读取索引。该锁将在整个事务中被持有。
USE AdventureWorks ;
GO
BEGIN TRAN
SELECT COUNT(*)
FROM HumanResources.Employee WITH (TABLOCK, HOLDLOCK) ;
C. 使用 SQL-92 CROSS JOIN 语法
下面的示例返回 Employee 和 Department 这两个表的叉积。所返回的列表包含 EmployeeID 行和所有 Department 名称行的所有可能的组合。
USE AdventureWorks ;
GO
SELECT e.EmployeeID, d.Name AS Department
FROM HumanResources.Employee AS e
CROSS JOIN HumanResources.Department AS d
ORDER BY e.EmployeeID, d.Name ;
D. 使用 SQL-92 FULL OUTER JOIN 语法
下面的示例返回产品名称以及 SalesOrderDetail 表中任何对应的销售订单。该示例还将返回在 Product 表中没有列出产品的任何销售订单,以及销售订单不同于在 Product 表中列出的销售订单的任何产品。
USE AdventureWorks ;
GO
-- The OUTER keyword following the FULL keyword is optional.
SELECT p.Name, sod.SalesOrderID
FROM Production.Product AS p
FULL OUTER JOIN Sales.SalesOrderDetail AS sod
ON p.ProductID = sod.ProductID
WHERE p.ProductID IS NULL OR sod.ProductID IS NULL
ORDER BY p.Name ;
E. 使用 SQL-92 LEFT OUTER JOIN 语法
下面的示例基于 ProductID 联接两个表,并保留左表中不匹配的行。Product 表与每个表中的 ProductID 列上的 SalesOrderDetail 表相匹配。所有产品,无论是否已订购,都将在结果集中显示。
USE AdventureWorks ;
GO
SELECT p.Name, sod.SalesOrderID
FROM Production.Product AS p
LEFT OUTER JOIN Sales.SalesOrderDetail AS sod
ON p.ProductID = sod.ProductID
ORDER BY p.Name ;
F. 使用 SQL-92 INNER JOIN 语法
下面的示例返回所有产品名称和销售订单 ID。
USE AdventureWorks ;
GO
-- By default, SQL Server performs an INNER JOIN if only the JOIN
-- keyword is specified.
SELECT p.Name, sod.SalesOrderID
FROM Production.Product AS p
INNER JOIN Sales.SalesOrderDetail AS sod
ON p.ProductID = sod.ProductID
ORDER BY p.Name ;
G. 使用 SQL-92 RIGHT OUTER JOIN 语法
下面的示例基于 TerritoryID 联接两个表,并保留右表中不匹配的行。SalesTerritory 表与每个表中的 TerritoryID 列上的 SalesPerson 表相匹配。不论是否分配了区域,所有销售人员均在结果集中显示。
USE AdventureWorks ;
GO
SELECT st.Name AS Territory, sp.SalesPersonID
FROM Sales.SalesTerritory AS st
RIGHT OUTER JOIN Sales.SalesPerson AS sp
ON st.TerritoryID = sp.TerritoryID ;
H. 使用 HASH 和 MERGE 联接提示
下面的示例在 Product、ProductVendor 和 Vendor 表之间执行三表联接,生成产品及其供应商的列表。查询优化器使用 MERGE 联接来联接 Product 和 ProductVendor(p 和 pv)。然后,Product 和 ProductVendor MERGE 联接(p 和 pv)的结果被 HASH 联接到 Vendor 表,生成(p 和 pv)和 v。
重要提示: |
|---|
|
指定了联接提示后,要执行 INNER JOIN 时,INNER 关键字不再为可选,而必须显式说明。
|
USE AdventureWorks ;
GO
SELECT p.Name AS ProductName, v.Name AS VendorName
FROM Production.Product AS p
INNER MERGE JOIN Purchasing.ProductVendor AS pv
ON p.ProductID = pv.ProductID
INNER HASH JOIN Purchasing.Vendor AS v
ON pv.VendorID = v.VendorID
ORDER BY p.Name, v.Name ;
I. 使用派生表
下面的示例使用派生表(FROM 子句后的 SELECT 语句)返回所有员工的名字和姓氏及其居住的城市。
USE AdventureWorks ;
GO
SELECT RTRIM(c.FirstName) + ' ' + LTRIM(c.LastName) AS Name,
d.City
FROM Person.Contact AS c
INNER JOIN HumanResources.Employee e ON c.ContactID = e.ContactID
INNER JOIN
(SELECT ea.AddressID, ea.EmployeeID, a.City
FROM Person.Address AS a
INNER JOIN HumanResources.EmployeeAddress AS ea
ON a.AddressID = ea.AddressID) AS d
ON e.EmployeeID = d.EmployeeID
ORDER BY c.LastName, c.FirstName;
J. 使用 TABLESAMPLE 从表中的行样本中读取数据
下面的示例在 FROM 子句中使用 TABLESAMPLE,大约返回 AdventureWorks 数据库中的 Customer 表中所有行的 10%。
USE AdventureWorks ;
GO
SELECT *
FROM Sales.Customer TABLESAMPLE SYSTEM (10 PERCENT) ;
K. 使用 APPLY
下面的示例假定数据库中存在具有如下架构的以下表:
-
Departments: DeptID, DivisionID, DeptName, DeptMgrID
-
EmpMgr: MgrID, EmpID
-
Employees: EmpID, EmpLastName, EmpFirstName, EmpSalary
还有一个表值函数 (GetReports(MgrID)) 可以返回指定的 MgrID 直接或间接领导的所有员工的列表(EmpID、EmpLastName、EmpSalary)。
该示例使用 APPLY 返回所有部门和部门中的所有员工。如果某个部门没有任何员工,则将不返回该部门的任何行。
SELECT DeptID, DeptName, DeptMgrID, EmpID, EmpLastName, EmpSalary
FROM Departments d CROSS APPLY dbo.GetReports(d.DeptMgrID) ;
如果您希望查询为那些没有员工的部门生成行(这将为 EmpID、EmpLastName 和 EmpSalary 列生成 Null 值),请改用 OUTER APPLY。
SELECT DeptID, DeptName, DeptMgrID, EmpID, EmpLastName, EmpSalary
FROM Departments d OUTER APPLY dbo.GetReports(d.DeptMgrID) ;
L. 使用 PIVOT 和 UNPIVOT
下面的示例返回按员工 ID(164、198、223、231 和 233)下达并按供应商 ID 分类的采购订单的数量。
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) AS 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
若要对表进行逆透视,请假定在上一个示例中生成的结果集是作为 pvt 存储的。该查询如下所示。
--Create the table and insert values as portrayed in the previous example.
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) AS 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
1 Emp5 4
2 Emp1 4
2 Emp2 1
2 Emp3 5
2 Emp4 5
2 Emp5 5