web-dev-qa-db-ja.com

別のテーブルにないIDを持つレコードを見つけるためのSQLクエリ

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

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

したがって、SQLクエリを作成して、table1にないtable2からIDを持つ行をフェッチするにはどうすればよいですか。この場合、(3, Mary)が返されますか?

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

前もって感謝します。

93
johnklee

これを試して

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

LEFT JOINを使用

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

高速代替

それぞれ〜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;
8
polvoazul

上記の@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
)
5
CaseyR

それには基本的に3つのアプローチがあります:not existsnot inleft join / is null

IS NULLで左結合

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 EXISTSLEFT JOIN / IS NULLの実行計画は同じです。個人的には、NOT EXISTSオプションを好むのは、意図がよりよくわかるからです。すべてのセマンティクスは、Aでそのpk 存在しない Bのレコードを検索することです。

古いが、まだPostgreSQLに特有であるが、 https://explainextended.com/2009/09/16/not-in-vs-not-exists-vs-left-join-is-null-postgresql/

3
L. Holanda
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
1
JoshYates1980