gpt4 book ai didi

sql-server - 创建笛卡尔积时,CROSS APPLY 和 OUTER APPLY 有什么区别吗?

转载 作者:行者123 更新时间:2023-12-02 22:20:19 25 4
gpt4 key购买 nike

在两个表之间创建笛卡尔积时,CROSS APPLYOUTER 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

使用交叉应用:

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');

使用外部应用:

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');

...所有这些都给了我预期的零行。

最佳答案

当应用的表或表值函数没有记录时,差异就会发挥作用:

SELECT      First.Id AS FirstId, Second.Id AS SecondId
FROM First
OUTER APPLY (SELECT * FROM Second WHERE Second.Id = -1) Second
WHERE First.Name IN ('First253', 'First3304');

2 rows returned


SELECT First.Id AS FirstId, Second.Id AS SecondId
FROM First
CROSS APPLY (SELECT * FROM Second WHERE Second.Id = -1) Second
WHERE First.Name IN ('First253', 'First3304');

0 rows returned

用OP自己的话来说:

不是您这样做的方式,因为从概念上讲,您在 APPLY 之后使用 WHERE 进行过滤(尽管计划显示引擎通过首先执行此操作进行优化) ;但如果您先显式过滤,然后像这样APPLY:

SELECT      First.Id AS FirstId, FilteredSecond.Id AS SecondId
FROM First
CROSS APPLY (SELECT Id FROM Second WHERE Name IN ('xxx')) FilteredSecond
WHERE First.Name IN ('First253', 'First3304');

您会看到差异,因为您会通过 OUTER 得到带有 NULL 的行,但没有通过 CROSS 得到行。

关于sql-server - 创建笛卡尔积时,CROSS APPLY 和 OUTER APPLY 有什么区别吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48460123/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com