CROSS APPLY
是 SQL Server 中的一种 JOIN 运算符,主要用于连接表值函数或子查询结果集,并将其应用于每一行。它与 INNER JOIN
类似,但更灵活,尤其是在处理表值函数时。CROSS APPLY
的结果类似于为主表的每一行运行一次表值函数或子查询。
CROSS APPLY
的用法详解
-
表值函数配合
CROSS APPLY
CROSS APPLY
常用于调用返回表格的表值函数(Table-Valued Functions, TVFs)。- 它会将每一行主表的数据传递给表值函数,并返回与之相关的结果。
-
子查询配合
CROSS APPLY
- 可以使用
CROSS APPLY
将子查询的结果应用到主表的每一行。
- 可以使用
-
与
OUTER APPLY
的区别CROSS APPLY
类似于INNER JOIN
,仅返回有匹配结果的行。OUTER APPLY
类似于LEFT JOIN
,即使没有匹配结果,也会返回主表的行(对应的列值为 NULL)。
实际例子
1. 使用表值函数
假设有一个表 Employees
,存储员工信息,还有一个表值函数 GetTopNProjects
,根据员工 ID 获取其参与的前 N 个项目:
-- 创建表值函数
CREATE FUNCTION GetTopNProjects (@EmployeeID INT, @TopN INT)
RETURNS TABLE
AS
RETURN
(
SELECT TOP (@TopN) ProjectID, ProjectName
FROM Projects WHERE EmployeeID = @EmployeeID
ORDER BY ProjectStartDate DESC
);
-- 查询员工的前 2 个项目
SELECT e.EmployeeID, e.Name, p.ProjectID, p.ProjectName
FROM Employees e
CROSS APPLY GetTopNProjects(e.EmployeeID, 2) p;
解释:
- 对于
Employees
表中的每一行,CROSS APPLY
调用GetTopNProjects
函数,并传递EmployeeID
和2
作为参数。 - 返回每个员工的前两个项目。
2. 使用子查询
假设有一个表 Orders
,存储订单数据,需要查询每个客户的最近一次订单:
SELECT c.CustomerID, c.CustomerName, o.OrderID, o.OrderDate
FROM Customers c
CROSS APPLY
(
SELECT TOP 1 OrderID, OrderDate
FROM Orders
WHERE Orders.CustomerID = c.CustomerID
ORDER BY OrderDate DESC
) o;
解释:
- 对于
Customers
表中的每一行,CROSS APPLY
执行子查询,获取该客户的最近一次订单。 - 结果包括客户信息及其最近的订单。
3. 计算派生列
假设需要为每个订单计算订单金额总和:
SELECT o.OrderID, o.CustomerID, t.TotalAmount
FROM Orders o
CROSS APPLY
(
SELECT SUM(Price * Quantity) AS TotalAmount
FROM OrderDetails
WHERE OrderDetails.OrderID = o.OrderID
) t;
解释:
CROSS APPLY
将子查询计算的结果(订单金额总和)附加到主表Orders
的每一行。
日常实际场景
- 分页数据 使用表值函数或子查询,动态获取每页的数据。
- 动态列生成 根据主表的某些字段动态计算并生成新的列。
- 业务规则 获取相关记录(如最近订单、最高分项目等)以满足复杂的业务需求。
CROSS APPLY
提供了一种灵活高效的方式,尤其在需要动态依赖主表数据计算时,表现出色!