是否有任何 objective 理由更喜欢一种特定形式的左反半连接?
Is there any objective reason to prefer a particular form of left anti-semi join?
我见过很多不同形式的左反半连接。请允许我列出并命名每一个想到的。以下查询旨在 return 每个 ROSTER_ID
未被任何员工使用且谁是该花名册的所有者。
--1) NOT EXISTS, with a particular column selected in the subquery
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
WHERE NOT EXISTS (SELECT EMP_ID FROM EMPLOYEES WHERE EMP_ID = ROSTERS.EMP_ID)
--2) NOT EXISTS, with a particular column selected in the subquery and TOP (1) used
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
WHERE NOT EXISTS (SELECT TOP (1) EMP_ID FROM EMPLOYEES WHERE EMP_ID = ROSTERS.EMP_ID)
--3) NOT EXISTS, with all data selected in the subquery
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
WHERE NOT EXISTS (SELECT * FROM EMPLOYEES WHERE EMP_ID = ROSTERS.EMP_ID)
--4) NOT EXISTS, with all columns selected in the subquery and TOP (1) used
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
WHERE NOT EXISTS (SELECT TOP (1) * FROM EMPLOYEES WHERE EMP_ID = ROSTERS.EMP_ID)
--5) NOT EXISTS, but just use SELECT 1
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
WHERE NOT EXISTS (SELECT 1 FROM EMPLOYEES WHERE EMP_ID = ROSTERS.EMP_ID)
--6) NOT IN
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
WHERE EMP_ID NOT IN (SELECT EMP_ID FROM EMPLOYEES)
--7) LEFT JOIN
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
LEFT OUTER JOIN EMPLOYEES
ON EMPLOYEES.EMP_ID = ROSTERS.EMP_ID
WHERE EMPLOYEES.EMP_ID IS NULL
我的问题是:是否有任何 objective 原因 - 例如性能、向后兼容性、可移植性、NULL 处理、易于测试、可扩展性等 - 更喜欢执行左反半连接的任何特定方式? 我也有兴趣听听主观原因,例如风格问题或清晰度,但只包括它们将是一个无法回答的问题。
我自己的研究仅指出以下几点,但都很薄弱,而且可能是主观的:
- Microsoft's U-SQL documentation 暗示他们更喜欢在 T-SQL.
中使用 NOT IN 版本(我的#6)
NULL
使用 IN
处理 总是 引起关注,这是一个更喜欢 EXISTS
而不是它的温和理由。
- 如果您非常关心向后兼容性,那么我认为我的 LEFT JOIN 语法在 1980 年代不起作用。
- 有些人喜欢使用
EXCEPT
,但我认为它不能推广到列只出现在最外层的情况SELECT
。
没有,除了不吸
Aaron 的文章已经充满了丰富的信息,您已经发现了将 NOT IN
与 NULLS 结合使用的危险。
我唯一可以补充的是,我没有注意到讨论的是,当使用 (not) exists
时,FROM
之前的东西,如 select column
或 select top 1 *
是如何本质上是垃圾。我什至向 sql 服务器发布了一条建议,建议使用 (anti) semi join table2 on <join condition>
.
的替代语法
EXISTS
, NOT EXISTS
return boolean TRUE/FALSE
depending.The Select
columns mention in EXISTS
subquery do not matter,它只根据 where cluase
检查它是否存在
例如,
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
WHERE NOT EXISTS (SELECT 1/0 FROM EMPLOYEES WHERE EMP_ID = ROSTERS.EMP_ID)
在上面的通知中 1/0
不会抛出错误,这是什么意思?
所以你的 1),2),3),4),5) 在性能和结果上都是一样的。
LEFT JOIN
:当您需要结果集中的 LEFT JOIN table 列时使用。
我不认为任何答案都涵盖了所有内容,因此我尝试将所有答案和评论放在一起:
- 示例1到5,即
EXISTS
示例,都是一样的。这不容易证明(您可能会发现 KumarHarsh 的示例很有说服力)并且依赖于您对优化器的信任。
- 不要使用示例 #6,即
IN
。你不能相信它 NULL
s.
- 示例 #7,即
LEFT JOIN
,如果您将其用于普通(即非 anti
)半连接,则可以复制结果。还有人怀疑优化器将如何处理它(参见下面的 link)。主观上,它需要看起来更多的打字,并且不太擅长传达您的意图。总的来说,最好避免。
总之,使用EXISTS
。使用 TOP
的示例 #2 和 #4 毫无意义,因此您最好避免使用它们。至于是否应该使用示例#1、#3 或#5,这只是个人喜好问题。我认为 #5 最清楚地传达了意图,但这完全是一个见仁见智的问题。
This very helpful article 也建议 OUTER APPLY
,但我认为没有人认真对待它。
我见过很多不同形式的左反半连接。请允许我列出并命名每一个想到的。以下查询旨在 return 每个 ROSTER_ID
未被任何员工使用且谁是该花名册的所有者。
--1) NOT EXISTS, with a particular column selected in the subquery
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
WHERE NOT EXISTS (SELECT EMP_ID FROM EMPLOYEES WHERE EMP_ID = ROSTERS.EMP_ID)
--2) NOT EXISTS, with a particular column selected in the subquery and TOP (1) used
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
WHERE NOT EXISTS (SELECT TOP (1) EMP_ID FROM EMPLOYEES WHERE EMP_ID = ROSTERS.EMP_ID)
--3) NOT EXISTS, with all data selected in the subquery
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
WHERE NOT EXISTS (SELECT * FROM EMPLOYEES WHERE EMP_ID = ROSTERS.EMP_ID)
--4) NOT EXISTS, with all columns selected in the subquery and TOP (1) used
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
WHERE NOT EXISTS (SELECT TOP (1) * FROM EMPLOYEES WHERE EMP_ID = ROSTERS.EMP_ID)
--5) NOT EXISTS, but just use SELECT 1
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
WHERE NOT EXISTS (SELECT 1 FROM EMPLOYEES WHERE EMP_ID = ROSTERS.EMP_ID)
--6) NOT IN
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
WHERE EMP_ID NOT IN (SELECT EMP_ID FROM EMPLOYEES)
--7) LEFT JOIN
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
LEFT OUTER JOIN EMPLOYEES
ON EMPLOYEES.EMP_ID = ROSTERS.EMP_ID
WHERE EMPLOYEES.EMP_ID IS NULL
我的问题是:是否有任何 objective 原因 - 例如性能、向后兼容性、可移植性、NULL 处理、易于测试、可扩展性等 - 更喜欢执行左反半连接的任何特定方式? 我也有兴趣听听主观原因,例如风格问题或清晰度,但只包括它们将是一个无法回答的问题。
我自己的研究仅指出以下几点,但都很薄弱,而且可能是主观的:
- Microsoft's U-SQL documentation 暗示他们更喜欢在 T-SQL. 中使用 NOT IN 版本(我的#6)
NULL
使用IN
处理 总是 引起关注,这是一个更喜欢EXISTS
而不是它的温和理由。- 如果您非常关心向后兼容性,那么我认为我的 LEFT JOIN 语法在 1980 年代不起作用。
- 有些人喜欢使用
EXCEPT
,但我认为它不能推广到列只出现在最外层的情况SELECT
。
没有,除了不吸
Aaron 的文章已经充满了丰富的信息,您已经发现了将 NOT IN
与 NULLS 结合使用的危险。
我唯一可以补充的是,我没有注意到讨论的是,当使用 (not) exists
时,FROM
之前的东西,如 select column
或 select top 1 *
是如何本质上是垃圾。我什至向 sql 服务器发布了一条建议,建议使用 (anti) semi join table2 on <join condition>
.
EXISTS
, NOT EXISTS
return boolean TRUE/FALSE
depending.The Select
columns mention in EXISTS
subquery do not matter,它只根据 where cluase
例如,
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
WHERE NOT EXISTS (SELECT 1/0 FROM EMPLOYEES WHERE EMP_ID = ROSTERS.EMP_ID)
在上面的通知中 1/0
不会抛出错误,这是什么意思?
所以你的 1),2),3),4),5) 在性能和结果上都是一样的。
LEFT JOIN
:当您需要结果集中的 LEFT JOIN table 列时使用。
我不认为任何答案都涵盖了所有内容,因此我尝试将所有答案和评论放在一起:
- 示例1到5,即
EXISTS
示例,都是一样的。这不容易证明(您可能会发现 KumarHarsh 的示例很有说服力)并且依赖于您对优化器的信任。 - 不要使用示例 #6,即
IN
。你不能相信它NULL
s. - 示例 #7,即
LEFT JOIN
,如果您将其用于普通(即非anti
)半连接,则可以复制结果。还有人怀疑优化器将如何处理它(参见下面的 link)。主观上,它需要看起来更多的打字,并且不太擅长传达您的意图。总的来说,最好避免。
总之,使用EXISTS
。使用 TOP
的示例 #2 和 #4 毫无意义,因此您最好避免使用它们。至于是否应该使用示例#1、#3 或#5,这只是个人喜好问题。我认为 #5 最清楚地传达了意图,但这完全是一个见仁见智的问题。
This very helpful article 也建议 OUTER APPLY
,但我认为没有人认真对待它。