本帖最后由 郑全 于 2025-10-10 15:38 编辑
今天看到一个 CROSS APPLY SQL语句,记录一下:
CROSS APPLY 是 SQL 中的一种表操作符,主要用于将表表达式(如子查询、表值函数)与左侧的表进行关联,类似于 JOIN,但更灵活,尤其适用于将左侧表的列作为参数传递给右侧的表值函数或子查询的场景。
核心作用
CROSS APPLY 会将左侧表的每一行与右侧表表达式(如函数)的结果进行 “交叉应用”,最终返回所有匹配的组合。
- 若右侧表表达式返回空结果,对应的左侧行不会出现在结果中(类似 INNER JOIN 的行为)。
- 若需要保留左侧行(即使右侧无结果),可使用 OUTER APPLY(类似 LEFT JOIN)。
语法格式
SELECT 列名 FROM 左侧表 CROSS APPLY ( 表值函数(左侧表.列名) -- 或子查询,可引用左侧表的列) AS 别名;
典型使用场景1. 与表值函数结合(最常用)
假设有一个表值函数 fn_GetOrdersByCustomerId(@CustomerId),用于返回指定客户的所有订单。
使用 CROSS APPLY 可一次性获取所有客户及其对应的订单:
-- 客户表
SELECT *
FROM Customers c
CROSS APPLY fn_GetOrdersByCustomerId(c.CustomerId) o;
等价于对每个客户执行一次函数,并将结果与客户信息关联。
2. 与子查询结合(引用左侧表列)
当子查询需要依赖左侧表的列作为条件时,CROSS APPLY 比普通 JOIN 更方便(JOIN 的子查询无法直接引用左侧表的列)。
例如,查询每个员工的最近 3 条销售记录:
SELECT e.EmployeeId, e.Name, s.SaleDate, s.Amount
FROM Employees e
CROSS APPLY ( -- 子查询引用左侧表的 EmployeeId
SELECT TOP 3 SaleDate, Amount
FROM Sales
WHERE EmployeeId = e.EmployeeId -- 依赖左侧表的列
ORDER BY SaleDate DESC) s;
3. 处理 JSON/XML 数据(提取嵌套内容)
在 SQL Server 中,可结合 OPENJSON 等函数解析 JSON 数据,用 CROSS APPLY 提取嵌套数组:
-- 假设有一张表存储 JSON 格式的订单明细
SELECT o.OrderId, j.ItemName, j.Quantity
FROM Orders o
CROSS APPLY OPENJSON(o.DetailsJson, '$.Items') -- 解析 JSON 数组
WITH ( ItemName VARCHAR(50) '$.Name', Quantity INT '$.Qty') j;
与 JOIN 的区别 特性 | CROSS APPLY | INNER JOIN | 右侧引用左侧列 | 允许(核心优势 ) | 不允许(子查询无法直接引用左侧表) | 适用场景 | 表值函数、依赖左侧列的子查询 | 基于等值 / 非等值条件的常规关联 | 空结果处理 | 右侧为空时,左侧行不保留 | 无匹配时,行不保留(与 CROSS APPLY 一致) |
注意事项- CROSS APPLY 是 SQL Server、Azure SQL 等数据库支持的语法,MySQL 不支持(MySQL 可用 LATERAL JOIN 替代,功能类似)。
- 若需保留左侧所有行(即使右侧无结果),使用 OUTER APPLY(右侧为空时返回 NULL)。
- 合理使用可简化复杂查询,但过度使用可能影响性能,需注意索引优化。
通过 CROSS APPLY,可以更灵活地处理 “行与依赖该行的子结果集” 的关联场景,尤其在表值函数和嵌套数据处理中非常实用。
|