cross apply 和 outer apply 的区别
使用 APPLY
APPLY 运算符的左操作数和右操作数都是表表达式。 这些操作数之间的主要区别是,right_table_source 可以使用表值函数,该函数可从 left_table_source 获取一个列作为函数的参数之一 。 left_table_source 可以包括表值函数,但不能以来自 right_table_source 的列作为参数。
APPLY 运算符通过以下方式工作,以便为 FROM 子句生成表源:
-
针对 left_table_source 的每一行计算 right_table_source 以生成行集 。
right_table_source 中的值取决于 left_table_source 。 right_table_source 可以按以下方式近似表示:
TVF(left_table_source.row)
,其中,TVF
是表值函数。 -
通过执行 UNION ALL 操作,将计算 right_table_source 的值时为每行生成的结果集与 left_table_source 组合起来 。
APPLY 运算符的结果生成的列的列表是来自 left_table_source(与来自 right_table_source 的列的列表相组合)的一组列 。
示例:
以下示例假定数据库中存在以下表和表值函数:
对象名称 | 列名 |
---|---|
Departments | DeptID、DivisionID、DeptName、DeptMgrID |
EmpMgr | MgrID、EmpID |
Employees | EmpID、EmpLastName、EmpFirstName、EmpSalary |
GetReports(MgrID) | EmpID、EmpLastName、EmpSalary |
GetReports
表值函数返回直接或间接报告给指定 MgrID
的所有员工的列表。
该示例使用 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);
总结: cross apply 是左边表和右边表,显示的是 关联条件都匹配的行
而outer apply 是以左边的表为主表,如果关联条件未匹配,仍然会显示行
apply多用于表值函数的时候。
参考:
FROM 子句,以及 JOIN、APPLY 和 PIVOT (T-SQL) - SQL Server | Microsoft Learn