別のテーブルに存在しない1つのテーブルからすべてのレコードを選択する方法は?


469

table1(id、name)
table2(id、name)

クエリ:

SELECT name   
FROM table2  
-- that are not in table1 already

回答:


843
SELECT t1.name
FROM table1 t1
LEFT JOIN table2 t2 ON t2.name = t1.name
WHERE t2.name IS NULL

Q:ここで何が起こっていますか?

A:概念的には、すべての行を選択しtable1、各行table2について、name列に同じ値を持つ行を見つけようとします。そのような行がない場合は、その行のtable2結果の部分を空のままにします。次に、一致する行が存在しない行のみを結果から選択して、選択を制限します。最後に、name列を除いて、結果からすべてのフィールドを無視します(存在することを確認したフィールド、from table1)。

すべてのケースで可能な最もパフォーマンスの高い方法ではないかもしれませんが、ANSI 92 SQLの実装を試みるすべてのデータベースエンジンで基本的に機能するはずです。


16
@ Z-ボス:それはまた、SQL Server上の少なくともパフォーマンスです:explainextended.com/2009/09/15/...
OMGポニー

7
@BunkerBoy:左結合では、左側の行の包含に影響を与えることなく、右側の行が存在しないようにすることができます。内部結合では、左側と右側に行が存在する必要があります。ここで私がやっていることは、基本的に内部結合の逆選択を取得するためにいくつかのロジックを適用することです。
クリス

2
これは非常に簡単に視覚化するのに役立ちました。他の人は5つの異なる方法でそれを表現しましたが、これは役立ちました。シンプル:最初に左結合を取得し、Aのすべて、およびAに一致するBのすべてを取得します。ただし、左結合では、結合しないフィールドは単にnullです。次に、あなたが言う、私はそれがnullであることだけを望みます。このようにして、Bで一致しなかったAのすべての行が表示されます
Muhammad Umer

7
このソリューション(承認および投票済み)が唯一のソリューションであることに注意してください。複数のフィールドが関係するシナリオで編集できると思います。具体的には、フィールド1とフィールド2のフィールド3を、フィールド1とフィールド2の組み合わせが2番目のテーブルにないテーブル1から返しています。この回答で結合を変更する以外に、以下で主張されている他の「より効率的な回答」のいくつかでそれを行う方法は
見当たりません

1
「AND」では正しい結果が得られないため、「AND t2.name IS NULL」ではなく「WHERE t2.name IS NULL」を使用してください。理由はよくわかりませんが、事実ですのでテストしました。
user890332

236

あなたはどちらかをすることができます

SELECT name
FROM table2
WHERE name NOT IN
    (SELECT name 
     FROM table1)

または

SELECT name 
FROM table2 
WHERE NOT EXISTS 
    (SELECT * 
     FROM table1 
     WHERE table1.name = table2.name)

これを達成する3つの手法については、この質問を参照


38
これは、大量のデータがあると信じられないほど遅くなります。
電球

ええ、確かに非常に遅いです
sirus

存在しないクエリのサブクエリの "from table1"であってはなりません。
ハウンド

これが非常に多くの賛成票を獲得した方法について非常に混乱しています。ほぼ同じ数のキーストロークで信じられないほど高速なこの問題へのアプローチがある場合、これを使用する理由を考えるのは非常に難しいと思います。
searchengine27

これは私のために働いた..ありがとう
タメーム

81

2番目の回答に投票するのに十分な担当者ポイントがありません。しかし、私は上の答えのコメントに同意しなければなりません。2番目の答え:

SELECT name
FROM table2
WHERE name NOT IN
    (SELECT name 
     FROM table1)

実際にはFARの方が効率的です。理由はわかりませんが、80万件以上のレコードに対して実行しているため、上記の2番目の回答に示されている利点との違いは非常に大きくなっています。たったの0.02ドル


30
NOT INクエリではサブクエリは1回だけ実行され、EXISTSクエリではすべての行に対してサブクエリが実行されます
Carrick

1
あなたは素晴らしいです:)このように、左結合を使用して25秒のクエリを0.1秒に変換します
Bassem Shahin '19

3
答えは特定の順序ではないので、2番目の答えは、あなたがそれが何を意味すると思ったかを意味しません。

38

これは、minus操作で実現できる純粋な集合論です。

select id, name from table1
minus
select id, name from table2

これは左結合よりもはるかに効率的だと思いますか?
ええと、2014

そのはず。マイナスコマンドは、この正確な状況のために設計されています。もちろん、特定のデータセットを判断する唯一の方法は、両方の方法を試して、どちらが速く実行されるかを確認することです。

9
T-SQLでは、集合演算子は "except"です。これは私にとって非常に便利で、速度低下を引き起こしていません。

2
SQLiteでは、「マイナス」演算子も「除外」されます。
lifjoy 2016

MySQLはMINUS演算子をサポートしていません。
ムハンマドアジーム


16

落とし穴に注意してください。のフィールドNameTable1Nullが含まれている場合は、驚きがあります。より良いです:

SELECT name
FROM table2
WHERE name NOT IN
    (SELECT ISNULL(name ,'')
     FROM table1)

1
COALESCE> ISNULL(ISNULLは、COALESCEよりも新しいまたはそれ以上の機能を持たない、この言語に対する無用のT-SQLの追加です)
Kris

14

これが私にとって最も効果的な方法です。

SELECT *
FROM @T1
EXCEPT
SELECT a.*
FROM @T1 a
JOIN @T2 b ON a.ID = b.ID

これは、私が試した他の方法の2倍以上の速さでした。


おかげで、これは大量のデータでもうまく機能します!しかし、私は「除外」という用語について疑問に思っています。
PatsonLeaner


7

それは私にとって鋭い働きをします

SELECT * 
FROM [dbo].[table1] t1
LEFT JOIN [dbo].[table2] t2 ON t1.[t1_ID] = t2.[t2_ID]
WHERE t2.[t2_ID] IS NULL

1

クエリを参照してください:

SELECT * FROM Table1 WHERE
id NOT IN (SELECT 
        e.id
    FROM
        Table1 e
            INNER JOIN
        Table2 s ON e.id = s.id);

概念的には、サブクエリで一致するレコードをフェッチしてから、メインクエリでサブクエリにないレコードをフェッチします。


0

(まだコメントするのに十分なほどクールではないので)正しい答えで再投稿します...他の誰かがより良い説明が必要だと思った場合に備えて。

SELECT temp_table_1.name
FROM original_table_1 temp_table_1
LEFT JOIN original_table_2 temp_table_2 ON temp_table_2.name = temp_table_1.name
WHERE temp_table_2.name IS NULL

また、mySQLのテーブル名の間にカンマが必要なFROMの構文を見てきましたが、sqlLiteではスペースを優先するように見えました。

肝心なのは、不正な変数名を使用すると疑問が残ることです。私の変数はもっと理にかなっているはずです。そして、誰かがコンマが必要な理由、またはコンマが不要な理由を説明する必要があります。


0

特定のユーザーで選択する場合

SELECT tent_nmr FROM Statio_Tentative_Mstr
WHERE tent_npk = '90009'
AND
tent_nmr NOT IN (SELECT permintaan_tent FROM Statio_Permintaan_Mstr)

tent_npkユーザーのプライマリキーです

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.