之前我问过一个关于替换使用SELECT DISTINCT的问题,因为查询需要花费更长的时间来执行。我被推荐使用EXISTS并且它工作得更好(0秒执行与之前的44秒执行。我不太熟悉查询语法但我正在学习。我希望有人可能能够重新编写以下查询而不使用DISTINCT并且最好使用EXISTS(因为它以前工作得很好)。我感谢任何帮助。
select distinct EM.Employee,
rtrim(EM.FirstName) + ' ' + rtrim(EM.LastName) as Name
from EM EM
inner join PR PR
on EM.Employee = PR.ProjMgr
where PR.WTS1 in (Select distinct WTS1
from TabFields
where custInclude = 'Y' and WTS2 = '')
and PR.WTS2 = ''
order by Name
答案 0 :(得分:1)
当您加入时,您将获得部分笛卡尔积。部分来自INNER JOIN条件。
因此对于EM中分别有3行和4行的2行,输出中会有7行。正如所料。你问“给我所有EM和PR的部分笛卡儿积的匹配行”
然而,你想要“给我在EM中的行,其中有PR的东西”。所以INNER JOIN是错误的构造。
你可以使用IN,EXISTS(或其他情况下的INTERSECT),它们在后一个问题上都是语义正确的。
在这种情况下,您使用IN的位置错误。正如我之前所说,整个“测试”条件应该被推入子查询。
所以,这两个都是正确的
停止加入!
select
EM.Employee, rtrim(EM.FirstName) + ' ' + rtrim(EM.LastName) as Name
from
EM EM
WHERE
EXISTS (SELECT *
FROM
PR PR
JOIN
TabFields TF ON PR.WTS1 = TF.WTS1
WHERE
PR.WTS2 = '' AND
TF.custInclude = 'Y' and TF.WBT2 = '' AND
EM.Employee = PR.ProjMgr
)
select
EM.Employee, rtrim(EM.FirstName) + ' ' + rtrim(EM.LastName) as Name
from
EM EM
WHERE
EM.Employee IN (SELECT PR.ProjMgr
FROM
PR PR
JOIN
TabFields TF ON PR.WTS1 = TF.WTS1
WHERE
PR.WTS2 = '' AND
TF.custInclude = 'Y' and TF.WBT2 = ''
)
使用更接近原始查询的2个IN:
select EM.Employee,
rtrim(EM.FirstName) + ' ' + rtrim(EM.LastName) as Name
from EM EM
WHERE
EM.Employee IN (SELECT PR.ProjMgr
FROM
PR PR
where PR.WTS1 in (Select distinct WTS1
from TabFields
where custInclude = 'Y' and WTS2 = '')
and PR.WTS2 = ''
)
order by Name
答案 1 :(得分:0)
如果您正在评估子查询,(新)查询优化器会将IN
视为与EXISTS
相同。
由于您使用的是IN
,因此您的子查询中不需要DISTINCT
。把它拿出来吧!
看起来有人正在编写查询并总是使用DISTINCT
,这是一个非常糟糕的习惯。 DISTINCT
只应用于避免重复。没有理由消除子查询中的欺骗,因为1
与1,2,1,3
中的1
一样准确,因为1,2,3
位于{{1}}。< / p>
答案 2 :(得分:0)
下面的代码不需要明确
select EM.Employee,
rtrim(EM.FirstName) + ' ' + rtrim(EM.LastName) as Name
from EM
inner join PR
on EM.Employee = PR.ProjMgr
where exists (Select *
from TabFields
where custInclude = 'Y' and WTS2 = '' and PR.WTS1 = tabfields.WTS1 )
and PR.WTS2 = '' -- Comment: Check if this clause is covered by the subquery and can be ommited
order by Name
答案 3 :(得分:0)
尝试使用GROUP BY而不是选择DISTINCT。您还可以从WHERE子句中移动子查询,并将其用作连接中的派生表。
SELECT EM.Employee,
RTRIM(EM.FirstName) + ' ' + RTRIM(EM.LastName) AS Name
FROM EM EM
INNER JOIN PR PR
ON EM.Employee = PR.ProjMgr
INNER JOIN (SELECT WTS1
FROM TabFields
WHERE custInclude = 'Y' AND WTS2 = ''
GROUP BY WTS1) x
ON PR.WTS1 = x.WTS1
AND PR.WTS2 = ''
GROUP BY EM.Employee, RTRIM(EM.FirstName) + ' ' + RTRIM(EM.LastName)
ORDER BY RTRIM(EM.FirstName) + ' ' + RTRIM(EM.LastName)
答案 4 :(得分:-1)
这个查询对我来说似乎很好。运行缓慢吗? 你真的需要修剪姓名吗?如果没有,你可以忽略它们。
select distinct E.Employee, rtrim(E.FirstName) + ' ' + rtrim(E.LastName) as Name
from EM E join PR P on E.Employee = P.ProjMgr
where P.WTS1 in (Select WTS1 from TabFields where custInclude = 'Y' and WTS2 = '')
and P.WTS2 = ''
order by Name
Exists()可用于在某些其他sqls执行之前将某些内容检查为条件。 如果你需要不同的行,exists()将无济于事。