2012-07-21 69 views
0

該查詢顯示正確的結果,但是在進行EXPLAIN時,它會將其列爲「依賴的子查詢」,我認爲它是不好的?從屬子查詢v左連接

SELECT Competition.CompetitionID, Competition.CompetitionName,  Competition.CompetitionStartDate 
FROM Competition 
WHERE CompetitionID NOT 
IN ( 
SELECT CompetitionID 
FROM PicksPoints 
WHERE UserID =1  
) 

我試圖改變查詢到這一點:

SELECT Competition.CompetitionID, Competition.CompetitionName, Competition.CompetitionStartDate 
FROM Competition 
LEFT JOIN PicksPoints ON Competition.CompetitionID = PicksPoints.CompetitionID 
WHERE UserID =1 
and PicksPoints.PicksPointsID is null 

,但它顯示0行。上述與第一個查詢相比,究竟有什麼問題呢?

回答

1

的秒數查詢不能產生行:它聲稱:

WHERE UserID =1 
and PicksPoints.PicksPointsID is null 

但要澄清,我改寫如下:

WHERE PicksPoints.UserID =1 
and PicksPoints.PicksPointsID is null 

所以,一方面,你所要求的行上PicksPoints其中UserId = 1,但是你又希望排在第一位不存在。你能看到失敗嗎?

外部連接是在那個如此棘手!通常你使用過濾器從「外」表列,例如Competition。但你不希望這樣做;您希望在左連接表進行篩選。嘗試並改寫如下:

SELECT Competition.CompetitionID, Competition.CompetitionName, Competition.CompetitionStartDate 
FROM Competition 
LEFT JOIN PicksPoints ON (Competition.CompetitionID = PicksPoints.CompetitionID AND UserID = 1) 
WHERE 
PicksPoints.PicksPointsID is null 

欲瞭解更多信息,請閱讀nice post

但是,作爲一個額外的注意事項,性能明智,你有一些麻煩,使用子查詢或左連接。

由於子查詢有困難,因爲高達5.6(其中一些很好的工作已經完成),MySQL對於優化內部查詢非常不利,並且您的子查詢需要多次執行。

隨着LEFT JOIN你有麻煩,因爲LEFT JOIN決定從左到右的連接順序。然而,你的過濾是在正確的表上,這意味着你將無法使用索引來過濾USerID = 1條件(或者你會失去連接的索引)。

+0

謝謝你,很好理解! – user1542043 2012-07-21 06:18:05

+0

+1關於性能問題的很好的鏈接和好的建議,但是你不認爲'UserId <> 1'是OP的第一個查詢的更好的翻譯嗎? – 2012-07-21 06:24:00

+0

'UserId <> 1'可能工作正常。我不確定哪個更清晰(或更少混淆:)) – 2012-07-21 06:53:30

0

這是兩個不同的查詢。第一個查詢查找與用戶標識1(通過PicksPoints表)關聯的競爭,其中第二個與那些與用戶標識1相關聯的那些行的那些行加入,競爭還具有空的PicksPointsID

第二個查詢將空出來,因爲您要加入一個名爲PicksPoints的表,並且您正在查找連接結果中具有PicksPointsID爲空的行。如果

  1. 第二個表有與第一臺相匹配的競爭ID空PickPointsID競爭ID行這隻能發生,或
  2. 所有列在第二個表的對連接的貢獻爲空,因爲第一個表中沒有出現競爭ID。

由於PicksPointsID確實聽起來像一個主鍵,它的情況2顯示出來。因此PickPointsID的所有列爲空,您的where子句(UserID=1 and PicksPoints.PicksPointsID is null)將始終爲假,並且您的結果將爲空。

一個普通的左連接應該爲你

select c.CompetitionID, c.CompetitionName, c.CompetitionStartDate 
from Competition c 
left join PicksPoints p 
on (c.CompetitionID = p.CompetitionID) 
where p.UserID <> 1 

and更換最終where(製備配合加盟條款)也可能攜手。我會留給你分析每個查詢的計劃。 :)

我沒有親自確信有必要對is null測試。 Shlomi Noach鏈接的文章非常好,你可以在這裏找到一些提示來幫助你。

+0

謝謝,有沒有辦法可以在「IN」中執行第一個查詢? – user1542043 2012-07-21 04:47:43

+0

添加到答案。 – 2012-07-21 06:23:29