如何解决事务 SQL ON EXISTS 语句
我有一个我不明白的 Transact SQL 问题。
我有 2 个表 tblMedewerker2 和 tblMedewerker3。
tblMedewerker2 为员工编号获得以下值:129、143,144,145,146,147,169。
tblMedewerker3 的员工编号为以下值:129、143,147、166,167,168。
它们分别包含 7 行和 9 行,因此值是唯一的。
以下查询产生 63 行:
select
a.employeenumber as emp_a,b.employeenumber as emp_b,isnull(a.employeenumber,b.employeenumber) as single_employeenumber
from tblMedewerker2 a
full join
tblMedewerker3 b
on exists
(
select a.employeenumber from tblMedewerker2
union
select b.employeenumber from tblmedewerker3
)
而此查询产生 10 行:
select
a.employeenumber as emp_a,b.employeenumber) as single_employeenumber
from tblMedewerker2 a
full join
tblMedewerker3 b
on exists
(
select a.employeenumber from tblMedewerker2
intersect
select b.employeenumber from tblmedewerker3
)
为什么第一个查询会将 SQL 变成某种 CROSS JOIN ?
我会说存在只是返回一个 TRUE 或一个 FALSE。那么为什么两个查询中的记录数量不同?
谢谢! Rgds BB
解决方法
这归结为所有 JOIN 的工作方式。让我们考虑一个简单的 INNER JOIN
SELECT a.id,b.id
FROM
a
INNER JOIN
b
ON a.id = b.id
这是说“将每一行与另一个表中的每一行进行比较。当 ON 条件为真时,将连接在一起的行包括在结果中”
现在考虑以下有效查询:
SELECT a.id,b.id
FROM
a
INNER JOIN
b
ON 1==1
同样,它的工作方式如上所述。 “将每一行与另一个表中的每一行进行比较。当 ON 条件为真时,将连接在一起的行包括在结果中”。在这种情况下,所有比较的 ON 条件都为真。
因此,如果左表有 7 行,而右表有 9 行,那么您将得到 63 行。 (我把它放在 SQL Fiddle 中让你自己看看:http://sqlfiddle.com/#!18/87097/17)
您在第一个查询中的 ON EXISTS
语句始终为真,因为您要加入的表中的任何行都可以在 UNION
中找到。它与我上面的 1==1 示例非常相似。在第一个查询中它是 FULL JOIN
的事实并不重要。如果是 LEFT JOIN
或 INNER JOIN
或 FULL JOIN
,它将返回 63 行。
在您的第二个查询中,ON 条件仅在有限的一组情况下为真:当被评估的行恰好位于两个表的交集时。
作为旁注。您的第二个查询可以简化为比较员工编号的常用 ON 子句。这是因为 ON 子句实际上取了两个表的交集。您可以将第二个查询编写为:
select
a.employeenumber as emp_a,b.employeenumber as emp_b,isnull(a.employeenumber,b.employeenumber) as single_employeenumber
from tblMedewerker2 a
full join
tblMedewerker3 b
on a.employeeNumber = b.employeeNumner
,
正如我在上面的评论中提到的,另一种解决方案(而不是笛卡尔积的答案和问题的交集部分)可能基于不同的方法——这只是草拟出来的,没有经过测试(这里很晚了,我我累了):
生成 CTE
的员工 ID 并将其 LEFT JOIN
到每个表
WITH EmployeeNumbers AS
SELECT DISTINCT employeenumber
FROM
(SELECT employeenumber FROM tblMedewerker2
UNION ALL
SELECT employeenumber FROM tblMedewerker2
) AS p
SELECT
t2.employeenumber AS empA,t3.employeenumber AS empB,ISNULL(t2.employeenumber,t3.employeenumber) AS single_employeenumber
-- an alternative to the above line
-- EN.employeenumber AS single_employeenumber
FROM
EmployeeNumbers AS EN
LEFT JOIN
tblMedewerker2 AS T2 ON EN.employeenumber = T2.employeenumber
LEFT JOIN
tblMedewerker3 AS T2 ON EN.employeenumber = T2.employeenumber
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。