2011-12-08 6 views
24

私はuserIDとtaskIDを含む1つのテンポラリテーブルを持っています。 CompletedTasksと呼ばれます。私はuserIDとtaskIDを含む2番目のテーブルを持っています。 PlannedTasksと呼ばれます。mysql "where not in" 2つのカラムを使用する

完了したが予定されていないすべてのtaskIDのリストを取得する必要があります。だから、私は何とか完了したタスクからすべての行を取り除く必要があります。PlannedTasks.userID != CompletedTasks.userID AND PlannedTasks.taskID != CompletedTasks.taskID

この質問は意味があると思います。不明な点がある場合はお知らせください。詳細を説明します。

ありがとうございました!

+0

ステータスを示すために追加の列が必要だと思いますが、本当に2つのテーブルは必要ありません。 – ajreal

+0

@ajrealそれは良い点です。おそらく、あなたが提案した方法でスキーマを調整することを検討します。ヒントをよろしく! – PFranchise

+1

私は、1つのテーブルと2つのテーブルより2つのテーブルと、その99%のステータスカラムを好んでいます。 1つのテーブルと11のステータスカラムを持つ11のテーブル。 1つまたは複数のステータス列(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のバージョンです。私の問題が解決

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

言及クエリの下に共有するためのおかげでypercubeᵀᴹ@

+0

恐ろしい!どうもありがとうございました。私はあなたがその方法で2つのフィールドでどこを使うことができるのか分かりませんでしたが、それがオプションになることを希望しました。もう一度ありがとう、素晴らしい一日を! – 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 

はしかし、私はコメントに同意する - 私たちは、ステータス列に2つのテーブルよりも優れたスキーマのように聞こえる質問から知っている与えられました。

0

+0

これはコメントでなければなりません。答え: – sniperd

+0

実際、@ypercubeの共有クエリを参照していくつかの変更を行いました。将来は気をつけます。ありがとう –