別のテーブルにないIDのレコードを検索するSQLクエリ


123

データベースに主キーをバインドする2つのテーブルがあり、それらの間にばらばらのセットを見つけたいと考えています。例えば、

  • Table1列(ID, Name)とサンプルデータがあります。(1 ,John), (2, Peter), (3, Mary)
  • Table2列(ID, Address)とサンプルデータがあります。(1, address2), (2, address2)

では、SQLクエリを作成して、にtable1ないIDの行をフェッチできるようにする方法を説明しますtable2。この場合、(3, Mary)返却する必要がありますか?

Ps。IDは、これら2つのテーブルの主キーです。

前もって感謝します。


3
今後の質問のヒントとして、使用しているデータベースシステム(およびそのデータベースのバージョン)を必ず定義してください。SQLは、ほとんどのデータベースシステムで使用されている構造化クエリ言語にすぎません。これはあまり役に立ちません...多くの場合、データベースには、問題の解決を容易にするANSI / ISO SQL標準をはるかに超える拡張機能と機能があります。使用しているデータベースを知らせる必要があります
marc_s

5
@marc_s:複数の基盤となるデータベースシステムをサポートする必要があるため、言語に依存しないソリューションを探している場合、またはデータベースの実装が抽象化されている場合はどうなりますか?
dwanderson 14年

こんにちは@marc_s、私はこの場合PostgreSQLを使用しています。思い出させてくれてありがとう。
ジョンクリー

回答:


213

これを試して

SELECT ID, Name 
FROM   Table1 
WHERE  ID NOT IN (SELECT ID FROM Table2)


20個のデータがある場合は機能しますが、20000個のデータがある場合は機能しません。Iamは混乱しています。
Frank

1
理由はわかりませんが、機能していません。テーブルには約10000行あります。私の場合、@ JohnWooのソリューションはうまくいきました。
Munam Yousuf 2017

4
この方法では値の数に制限があるため、「Not In」の値が多すぎても機能しませんcf:dba-oracle.com/t_maximum_number_of_sql_in_list_values.htm
G.Busato

2
私はこのようにする必要がありました:Table1からiを選択しますWHERE i NOT IN(SELECT i FROM Table2 where i is not null)and i is not null
jaksco

93

使用する LEFT JOIN

SELECT  a.*
FROM    table1 a
            LEFT JOIN table2 b
                on a.ID = b.ID
WHERE   b.id IS NULL

これは非常に大規模なデータベースの方が速いアプローチだと思います
Alex Jolig

12

そこと3つのアプローチは、基本的には、次のとおりですnot existsnot inleft join / is null

IS NULLを指定したLEFT JOIN

SELECT  l.*
FROM    t_left l
LEFT JOIN
        t_right r
ON      r.value = l.value
WHERE   r.value IS NULL

ありませんで

SELECT  l.*
FROM    t_left l
WHERE   l.value NOT IN
        (
        SELECT  value
        FROM    t_right r
        )

存在しない

SELECT  l.*
FROM    t_left l
WHERE   NOT EXISTS
        (
        SELECT  NULL
        FROM    t_right r
        WHERE   r.value = l.value
        )

どちらがいいですか?この質問への答えは、主要な特定のRDBMSベンダーに分類する方がよいでしょう。一般的に言えば、select ... where ... in (select...)サブクエリのレコード数の大きさが不明な場合は、使用を避ける必要があります。一部のベンダーはサイズを制限する場合があります。たとえば、Oracleの上限は1,000です。最善の方法は、3つすべてを試して実行計画を示すことです。

具体的にはPostgreSQLの実行計画を形成NOT EXISTSし、LEFT JOIN / IS NULL同じです。私は個人的にこのNOT EXISTSオプションを好みます。結局のところ、そのpk Bに存在しないというAのレコードを検索したいという意味です。

古いがまだゴールド、PostgreSQL固有:https : //explainextended.com/2009/09/16/not-in-vs-not-exists-vs-left-join-is-null-postgresql/


10

高速代替

それぞれ約2M行の2つのテーブルを使用して、いくつかのテスト(postgres 9.5)を実行しました。以下のクエリは、提案されている他のクエリよりも少なくとも5 *優れています。

-- Count
SELECT count(*) FROM (
    (SELECT id FROM table1) EXCEPT (SELECT id FROM table2)
) t1_not_in_t2;

-- Get full row
SELECT table1.* FROM (
    (SELECT id FROM table1) EXCEPT (SELECT id FROM table2)
) t1_not_in_t2 JOIN table1 ON t1_not_in_t2.id=table1.id;

1
これは、@ Jhon Wooのソリューションよりも速くはありませんでした。私はPostgres 9.6を使用していますが、Jhonのソリューションのランタイムは約60msです。私は120秒後にこの解決策をかなり行いましたが結果はありませんでした。
froy001

5

上記の@John Wooのコメント/リンクで行われたポイントを念頭に置いて、これは通常私がそれを処理する方法です。

SELECT t1.ID, t1.Name 
FROM   Table1 t1
WHERE  NOT EXISTS (
    SELECT TOP 1 NULL
    FROM Table2 t2
    WHERE t1.ID = t2.ID
)

2
SELECT COUNT(ID) FROM tblA a
WHERE a.ID NOT IN (SELECT b.ID FROM tblB b)    --For count


SELECT ID FROM tblA a
WHERE a.ID NOT IN (SELECT b.ID FROM tblB b)    --For results
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.