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 APPLYCROSS APPLY 而不是内连接或左外连接?

所以如果可能的话,请使用相同的场景,应该使用OUTER APPLY or CROSS APPLY,谢谢

【问题讨论】:

您可以在可以使用joins 的情况下使用它们。您可以将apply 用于join 不容易工作的其他情况,例如调用表值函数、从相关子查询返回多行以及从每个匹配项中提取前 行。 @Gordon Linoff :- 你能给出你所说的一小部分样本吗?谢谢 【参考方案1】:

这是一个不能重写为 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 中的记录

SQL Server:APPLY表运算符

为啥 T-SQL CROSS APPLY 有时表现得像 LEFT JOIN

T-SQL中的APPLY用法

SQL Server JOINS:SQL Server 中是不是默认关联“JOIN”语句“LEFT OUTER”? [复制]

SQL Server Join方式