CROSS APPLY
在两个表之间创建笛卡尔积时,和之间有什么区别OUTER APPLY
吗?
这似乎是一个愚蠢的问题,因为如果表格之间没有表达关系,右手边的表格不能不满足这种关系,但我尊重我不知道的东西。
当我使用简单的测试设置查看执行计划时,它们是相同的[两个索引搜索进入嵌套循环(内部连接)],但简单的测试设置可能具有欺骗性。
这是我的意思的一个例子(SQL Fiddle)。设置:
CREATE TABLE dbo.First (
Id INT IDENTITY(1, 1) PRIMARY KEY,
Name NVARCHAR(100)
);
GO
DECLARE @n INT = 1;
WHILE @n < 10000
BEGIN
INSERT INTO dbo.First (Name) VALUES ('First' + CONVERT(NVARCHAR(100), @n));
SET @n = @n + 1;
END
GO
CREATE INDEX IX__First__Name ON dbo.First(Name);
GO
CREATE TABLE dbo.Second (
Id INT IDENTITY(1, 1) PRIMARY KEY,
Name NVARCHAR(100)
);
GO
DECLARE @n INT = 1;
WHILE @n < 10000
BEGIN
INSERT INTO dbo.Second (Name) VALUES ('Second' + CONVERT(NVARCHAR(100), @n));
SET @n = @n + 1;
END
GO
CREATE INDEX IX__Second__Name ON dbo.Second(Name);
GO
使用CROSS APPLY
:
SELECT First.Id AS FirstId, Second.Id AS SecondId
FROM First
CROSS APPLY Second
WHERE First.Name IN ('First253', 'First3304')
AND Second.Name IN ('Second6543', 'Second517');
使用OUTER APPLY
:
SELECT First.Id AS FirstId, Second.Id AS SecondId
FROM First
OUTER APPLY Second -- <== Only change is here
WHERE First.Name IN ('First253', 'First3304')
AND Second.Name IN ('Second6543', 'Second517');
...两者都给了我预期的四行。
加上各种变体,其中一个或两个IN
子句都不返回匹配项:
-- No match in First
SELECT First.Id AS FirstId, Second.Id AS SecondId
FROM First
CROSS APPLY Second
WHERE First.Name IN ('no match')
AND Second.Name IN ('Second6543', 'Second517');
SELECT First.Id AS FirstId, Second.Id AS SecondId
FROM First
OUTER APPLY Second
WHERE First.Name IN ('no match')
AND Second.Name IN ('Second6543', 'Second517');
-- No match in Second
SELECT First.Id AS FirstId, Second.Id AS SecondId
FROM First
CROSS APPLY Second
WHERE First.Name IN ('First253', 'First3304')
AND Second.Name IN ('no match');
SELECT First.Id AS FirstId, Second.Id AS SecondId
FROM First
OUTER APPLY Second
WHERE First.Name IN ('First253', 'First3304')
AND Second.Name IN ('no match');
-- No match in either
SELECT First.Id AS FirstId, Second.Id AS SecondId
FROM First
CROSS APPLY Second
WHERE First.Name IN ('no match')
AND Second.Name IN ('no match');
SELECT First.Id AS FirstId, Second.Id AS SecondId
FROM First
OUTER APPLY Second
WHERE First.Name IN ('no match')
AND Second.Name IN ('no match');
...所有这些都给了我预期的零行。