我正在阅读有关使用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
感谢
答案 0 :(得分:5)
这是一个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在相应的内表列中。
答案 1 :(得分:2)
您要做的一件相对常见的事情是根据拆分器将列拆分为多个值。因此,Web上有各种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和数据处理的关键思想。