繁体   English   中英

SQL Server的指南APPLY AND JOIN关键字

[英]Guideline for SQL Server APPLY AND JOIN Keyword

我正在阅读一篇关于使用apply & join关键字的文章。 查看一些SQL,其中一个示例使用内部联接和其他使用apply关键字。

这是表pic

在此输入图像描述

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谢谢

这是一个APPLY示例,无法重写为JOIN:

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 子查询可用,因为APPLY允许相关。 最重要的用例是表值函数,如我原始示例中所示,因为APPLY允许将'main'表的列作为参数传递给函数。

CROSS APPLY和OUTER APPLY之间的区别与JOIN完全相同,OUTER情况允许返回匹配的行(APPLY返回空结果集),并在相应的内部表列中使用NULL。

您想要做的一件相对常见的事情是根据拆分器将列拆分为多个值。 因此,Web上有各种split()函数(实际上是批量和批量)。 以下是从这个问题的随机答案中得出的一个小例子:

  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和数据处理的关键思想。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM