2011-06-20 54 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)