2011-12-08 41 views
24

好吧,所以我有一個包含userID和taskID的臨時表。它被稱爲CompletedTasks。我有第二個表包含用戶ID和任務ID。它被稱爲PlannedTasks。mysql「哪裏不在」使用兩列

我需要獲得已完成但未計劃的所有任務ID的列表。所以,我需要以某種方式從完成的任務中清除所有行,其中兩個都是PlannedTasks.userID != CompletedTasks.userID AND PlannedTasks.taskID != CompletedTasks.taskID

我希望這個問題有道理。請讓我知道,如果不清楚,我會進一步解釋。

感謝您的任何提示!

+0

我想你需要一個額外的列來指示狀態,並不需要兩個表。 – ajreal

+0

@ajreal這是一個很好的觀點。也許我會考慮按照你的建議調整模式。欣賞提示! – PFranchise

+1

我比99%的時間更喜歡一張桌子和一張狀態欄上的2張桌子。一張桌子上有11張桌子,還有10張狀態欄。要優化搜索一個或多個狀態列(在Mysql中)的查詢並不容易。 –

回答

62

你可以使用這個(更緊湊語法):

SELECT * 
FROM CompletedTasks 
WHERE (userID, taskID) NOT IN 
     (SELECT userID, taskID 
     FROM PlannedTasks 
    ) ; 

NOT EXISTS版本(雖然比較複雜,應該是適當的索引更高效):

SELECT c.* 
FROM CompletedTasks AS c 
WHERE NOT EXISTS 
     (SELECT 1 
     FROM PlannedTasks AS p 
     WHERE p.userID = c.userID 
      AND p.taskID = c.taskID 
    ) ; 

,當然還有@jmacinnes在他的回答中提供的LEFT JOIN/IS NULL版本。

+0

太棒了!非常感謝你。我不知道你可以用這種方式在兩個地方使用Where,但希望這是一個選擇。再次感謝,祝你有美好的一天! – PFranchise

+0

繼我的測試後,NOT EXISTS版本比NOT_IN版本 –

+0

@Ka更快。是的,帶有元組的'NOT IN'沒有像'NOT EXISTS'那樣優化。你測試過哪個版本?我還沒有測試過它們是否改進了新5.7版本的優化器。 –

5

這是你需要的嗎?

select ct.* from 
completedTasks ct 
left outer join plannedTasks pt on ct.taskId = pt.TaskId and ct.userId = pt.userId 
where pt.taskId is null 

不過,我同意評論 - 鑑於我們從狀態欄聽起來比兩個表一個更好的架構問題知道。

0

@ypercubeᵀᴹ感謝分享以下提到的查詢

SELECT * FROM CompletedTasks WHERE (userID, taskID) NOT IN 
     (SELECT userID, taskID FROM PlannedTasks) ;' 

我的問題就迎刃而解了。

+0

這應該是一個評論,而不是答案:) – sniperd

+0

其實,我參考@ypercube共享查詢做了一些更改。將來會保重。謝謝 –