我对SQL Server有一个小问题.我们何时使用cross apply
,何时使用inner join
?为什么cross apply
在SQL Server中使用?
我有emp,dept表; 基于这两个表的,我写的inner join
和cross apply
查询这样的:
----using cross apply SELECT * FROM Department D CROSS APPLY (SELECT * FROM Employee E WHERE E.DepartmentID = D.DepartmentID) A ----using inner join SELECT * FROM Department D INNER JOIN Employee E ON D.DepartmentID = E.DepartmentID
两个查询都返回相同的结果.
这里为什么cross apply
需要SQL Server?有性能差异吗?你能告诉我吗?
我们cross apply
何时使用何时使用inner join
?这些查询之间的任何性能差异?请告诉我在SQL Server中编写此查询的最佳方法是什么.
INNER JOIN
和CROSS APPLY
(同与LEFT JOIN
和OUTER APPLY
)的关系非常密切.在您的示例中,我假设引擎将找到相同的执行计划.
A JOIN
是条件下两组之间的链接
a APPLY
是逐行子调用
但是 - 如上所述 - 优化器非常智能,并且 - 至少在如此简单的情况下 - 理解,它会归结为相同.
该JOIN
会尽量收集子集,并将其链接在特定的条件
该APPLY
会尝试打电话与当前行的值的相关结果,一遍又一遍.
差异在于使用XML方法和更复杂的场景调用表值函数(应该是内联的 -syntax!).nodes()
.
APPLY
用来模拟变量...使用行式计算的结果,就像使用变量一样:
DECLARE @dummy TABLE(ID INT IDENTITY, SomeString VARCHAR(100)); INSERT INTO @dummy VALUES('Want to split/this at the two/slashes.'),('And/this/also'); SELECT d.ID ,d.SomeString ,pos1 ,pos2 ,LEFT(d.SomeString,pos1-1) ,SUBSTRING(d.SomeString,pos1+1,pos2-pos1-1) ,SUBSTRING(d.SomeString,pos2+1,1000) FROM @dummy AS d CROSS APPLY(SELECT CHARINDEX('/',d.SomeString) AS pos1) AS x CROSS APPLY(SELECT CHARINDEX('/',d.SomeString,x.pos1+1) AS pos2) AS y
这与以下相同,但更容易阅读(和键入):
SELECT d.ID ,d.SomeString ,LEFT(d.SomeString,CHARINDEX('/',d.SomeString)-1) ,SUBSTRING(d.SomeString,CHARINDEX('/',d.SomeString)+1,CHARINDEX('/',d.SomeString,(CHARINDEX('/',d.SomeString)+1))-(CHARINDEX('/',d.SomeString)+1)) ,SUBSTRING(d.SomeString,CHARINDEX('/',d.SomeString,(CHARINDEX('/',d.SomeString)+1))+1,1000) FROM @dummy AS d
.nodes()
DECLARE @dummy TABLE(SomeXML XML) INSERT INTO @dummy VALUES (N'a1 a2 a3 Here is b! '); SELECT All_a_nodes.value(N'.',N'nvarchar(max)') FROM @dummy CROSS APPLY SomeXML.nodes(N'/root/a') AS A(All_a_nodes);
结果
a1 a2 a3
CREATE FUNCTION dbo.TestProduceRows(@i INT) RETURNS TABLE AS RETURN SELECT TOP(@i) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS Nr FROM master..spt_values GO CREATE TABLE dbo.TestData(ID INT IDENTITY, SomeString VARCHAR(100),Number INT); INSERT INTO dbo.TestData VALUES ('Show me once',1) ,('Show me twice',2) ,('Me five times!',5); SELECT * FROM TestData CROSS APPLY dbo.TestProduceRows(Number) AS x; GO DROP TABLE dbo.TestData; DROP FUNCTION dbo.TestProduceRows;
结果
1 Show me once 1 1 2 Show me twice 2 1 2 Show me twice 2 2 3 Me five times! 5 1 3 Me five times! 5 2 3 Me five times! 5 3 3 Me five times! 5 4 3 Me five times! 5 5