SQL Server APPLY AND JOIN 关键字指南
Posted
技术标签:
【中文标题】SQL Server APPLY AND JOIN 关键字指南【英文标题】:Guideline for SQL Server APPLY AND JOIN Keyword 【发布时间】:2014-03-18 11:22:06 【问题描述】:我正在阅读一篇关于使用apply & join
关键字的文章。查看一些 SQL,其中一个示例使用内部联接,而其他示例使用 apply 关键字。
这是表格图片
SELECT E.EMPID, E.NAME, E.DEPTID, D.NAME
FROM EMPLOYEE E
INNER JOIN DEPARTMENT D ON E.DEPTID = D.DEPTID
SELECT E.EMPID, E.NAME, E.DEPTID, CA.NAME
FROM EMPLOYEE E
CROSS APPLY
(SELECT * FROM DEPARTMENT D WHERE D.DEPTID = E.DEPTID) CA
两个查询都返回相同的输出和相同的执行计划。这是图片
再次使用外部应用和左外部连接
SELECT E.EMPID, E.NAME, E.DEPTID, D.NAME
FROM EMPLOYEE E
LEFT JOIN DEPARTMENT D ON E.DEPTID = D.DEPTID
SELECT E.EMPID, E.NAME, E.DEPTID, OA.NAME
FROM EMPLOYEE E
OUTER APPLY
(SELECT * FROM DEPARTMENT D WHERE D.DEPTID = E.DEPTID) OA
现在两个查询再次产生相同的输出和相同的执行计划。所以我只是不明白在什么样的情况下应该使用OUTER APPLY
或CROSS APPLY
而不是内连接或左外连接?
所以如果可能的话,请使用相同的场景,应该使用OUTER APPLY or CROSS APPLY
,谢谢
【问题讨论】:
您可以在可以使用join
s 的情况下使用它们。您可以将apply
用于join
不容易工作的其他情况,例如调用表值函数、从相关子查询返回多行以及从每个匹配项中提取前这是一个不能重写为 JOIN 的 APPLY 示例:
SELECT ...
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
您可以将 APPLY 视为关联关系的 JOIN。 JOIN 不允许关联,两个连接的关系必须是独立的。例如,以下是不正确的:
select *
from sys.objects o1
join (
select *
from sys.objects o2
where o1.object_id = o2.object_id) as o3
on 1=1;
Msg 4104, Level 16, State 1, Line 6
The multi-part identifier "o1.object_id" could not be bound.
但是,同样可以表示为 APPLY:
select *
from sys.objects o1
cross apply (
select *
from sys.objects o2
where o1.object_id = o2.object_id) as o3;
o1.object_id
is 在子查询中可用,因为 APPLY 允许关联。最重要的用例是表值函数,就像我最初的示例一样,因为 APPLY 允许将“主”表的列作为参数传递给函数。
CROSS APPLY 和 OUTER APPLY 之间的区别与 JOIN 完全相同,OUTER 情况允许返回不匹配的行(APPLY 返回空结果集),并带有 NULL在相应的内表列中。
【讨论】:
CROSS Apply 表示交叉连接?是笛卡尔积吗??【参考方案2】:您想要做的一个相对常见的事情是基于拆分器将一列拆分为多个值。因此,网络上有各种split()
功能(实际上很多很多)。 Here 是一个小例子,来源于对此类问题的随机回答:
SELECT d.RawKey, d.delimitedstring, d.delimitedvalues,
c.items SplitString,
c.rn
FROM dbo.tblRawData d CROSS APPLY
dbo.Split(d.DelimitedString, ',') c
这将是杀手级应用,因为在 SQL 语句中没有其他方法可以做到这一点。
另一种情况是返回多个可能有相关子查询的值:
select t1.*,
(select t2.col from table2 t2 where t2.col1 = t1.col2) as newcol
from table1 t1;
很简单,但是如果您想返回多个列,则需要多个子查询。而是:
select t1.*, t2.*
from table1 t1 cross apply
(select t2.col1, t2.col3, t2.col4
from table2 t2
where t2.col1 = t1.col2
) t2;
这可能是使用其他运算符编写的(尤其是在这种简单的情况下)。但是如果table2
真的是多张表和其他逻辑联结在一起的话,重写这个可能相当复杂。
不过,一般来说,您应该在适当的时候坚持使用join
。也许在 10 年后,这看起来会像 from
子句中的 ,
一样“过时”。但就目前而言,连接是 SQL 和数据处理中的一个关键思想。
【讨论】:
以上是关于SQL Server APPLY AND JOIN 关键字指南的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server:仅使用一次 Join/Cross Apply 中的记录
为啥 T-SQL CROSS APPLY 有时表现得像 LEFT JOIN
SQL Server JOINS:SQL Server 中是不是默认关联“JOIN”语句“LEFT OUTER”? [复制]