2011-06-20 26 views
0

我之前问过一个关于使用SELECT DISTINCT的替换的问题,因为查询需要很长时间才能执行。我被推荐使用EXISTS,并且它更好地工作(0秒执行,而之前的44秒执行。)我不太熟悉查询语法,但是我正在学习。我希望有人可能能够改写下面的查询而不使用DISTINCT,最好使用EXISTS(因为它的工作这么好之前)。我感谢所有帮助。SQL Server - 选择独特的替代查询

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 
+4

您应该尝试理解您之前的问题的答案并将其应用于此问题。如果你只是将论坛的答案复制粘贴到你的代码中,而不是试图理解,那么你正在走向成为代码猴的下坡阶段...... –

+1

+ 100000000000000000 Remus指出它对**更重要了解**你在做什么。 – JNK

+0

这是相同的查询,但你以前有过什么消毒?仅供参考:http://stackoverflow.com/q/6414550/27535 – gbn

回答

-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 

是否存在(),然后才能使用这样检查的东西作为一个条件我其他sqls被执行。 如果您需要不同的行,exists()将无济于事。

+0

是的,它运行缓慢,所以我一直在试图优化它。上面的第一个查询需要37秒来执行。 –

+0

EM表中有多少行?第二个需要多长时间?两个查询都是相同的,除了第二个使用联接而不是子查询。 – kheya

+0

第二个在0秒内执行,但当我只希望返回33行时返回143行。你写的第一个例子也返回33. –

0

如果您正在评估子查询,(新)查询优化器将把INEXISTS相同。

由于您使用的是IN,因此子查询中不需要DISTINCT。把它拿出来!

它看起来像有人正在写查询,并总是使用DISTINCT这是一个非常可怕的习惯进入。 DISTINCT只能用于避免重复。没有理由消除子查询中的欺骗,因为它可以准确地说11,2,1,3中,因为它是说11,2,3中。

1

当您加入时,您会得到部分笛卡尔产品。部分来自INNER JOIN条件。

因此,对于EM中分别有3行和4行的2行,输出中会得到7行。如预期。你问:“给我所有匹配行的EM和PR的部分笛卡尔乘积”

但是,你想要“给我在EM里有行的地方有PR的东西”。所以INNER JOIN是错误的结构。

您可以使用IN,EXISTS(或其他情况下的INTERSECT),并且它们对于后一个问题在语义上都是正确的。

在这种情况下,您使用IN是错误的地方。正如我之前所说,整个“测试”条件应该推入子查询中。

因此,这两种都是正确的

  • 一个表在FROM子句中
  • 子查询
  • 没有明显

停止所有的加盟条件!

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英寸更接近原始查询:

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 
+0

谢谢。我没有编写原始查询,并且正在修改由其他人创建的现有查询。我非常感谢你的帮助。再次感谢。 –

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 
0

尝试使用GROUP BY而不是SELECT 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)