2011-07-26 218 views
0

我有一個名爲Staff的表和一個名爲Supervisors的表。SQL慢嵌套查詢

人員有StaffIDFirstNameLastName,等...

監事包含RelationshipIDStaffIDSupervisorIDSetBySetOnStatus

基本上,主管表爲我們提供了員工自我關係的審計線索。我們有一張員工表,我們有一張員工表:員工關係(主管:員工)和一些額外信息(過時的,最新的,不正確的)以及設置它的時間和設置時間的StaffID。

現在,我在寫一個查詢來查找所有孤兒職員。我有:

SELECT * 
    FROM Staff 
WHERE StaffID NOT IN (SELECT StaffID 
         FROM Supervisors 
         WHERE Status = 0 
          OR Status = 2); 

(狀態0是從企業DB和2初始加載修改已經覈實了所有其它的是「過時的」,「不正確」,等等記錄。)

的問題是我有超過6000名員工和超過5000名員工:主管關係,這基本上是一個NxM查詢,意味着MySQL必須篩選300萬個排列組合。

我不是SQL忍者,有沒有更好的方法來做到這一點?

(注意,我不希望被經常運行在所有這類查詢)

+2

我不能想象,如果你有合適的指標來代替,這將是非常緩慢的。如果您尚未查看'StaffId'和'Status',請設置索引並查看查詢速度下降。 – AlienWebguy

+0

@AlienWebuy它實際上超時了30秒的php限制,但我修改了數據庫以獲得更多索引,而現在OMG Ponies的查詢所需時間不到一秒。 – Ozzah

回答

3

假設SUPERVISOR.staffidSUPERVISOR.status不可爲空,使用:

SELECT st.* 
    FROM STAFF st 
LEFT JOIN SUPERVISOR s ON s.staffid = st.staffid 
         AND s.status NOT IN (0,2) 
    WHERE s.staffid IS NULL 

否則,NOT IN/NOT EXISTS是等效&執行更好,如果列是空。

欲瞭解更多信息:

+0

upvoted你的答案(和編輯我的) –

3

這將更好地執行爲聯合而不是NOT IN:

SELECT st.* 
FROM Staff st 
LEFT JOIN Supervisors su ON st.StaffID = su.StaffID 
      AND (su.Status <> 0 AND su.Status <> 2) 
WHERE su.StaffId IS NULL 

下面是我把它改造:通過應用布爾的法律

NOT IN (SELECT StaffID FROM Supervisors WHERE Status = 0 OR Status = 2) 

相當於

IN (SELECT StaffID FROM Supervisors WHERE Status <> 0 AND Status <> 2); 

(假設Status永遠不能爲NULL),並且只有一個連接。

+0

對不起,我可能沒有具體說明:有些員工_沒有主管關係,即在Supervisor表中沒有包含StaffID的記錄。當我用我的初始數據運行查詢(_all_狀態爲== 0)時,我只用與IN相同的結果,而不是IN,這不是我所需要的。我需要找到孤兒工作人員。 – Ozzah

+0

Ozzah :我已更新。如果你接受任何答案,我建議接受OMG小馬的答案。 –