163

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

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

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

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

4

6 に答える 6

257

これを試して

SELECT ID, Name 
FROM   Table1 
WHERE  ID NOT IN (SELECT ID FROM Table2)
于 2012-08-21T05:01:18.750 に答える
127

使用するLEFT JOIN

SELECT  a.*
FROM    table1 a
            LEFT JOIN table2 b
                on a.ID = b.ID
WHERE   b.id IS NULL
于 2012-08-21T05:00:51.207 に答える
32

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

ISNULLの左結合

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オプションを好みます。なぜならそれは意図をよりよく示すからです。結局のところ、セマンティクスは、そのpkがBに存在しないAのレコードを検索することです。

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

于 2019-04-04T23:47:23.930 に答える
11

高速代替

それぞれ最大200万行の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;
于 2016-08-23T14:04:20.607 に答える
5

上記の@JohnWooのコメント/リンクで指摘された点を念頭に置いて、これが私が通常それを処理する方法です。

SELECT t1.ID, t1.Name 
FROM   Table1 t1
WHERE  NOT EXISTS (
    SELECT TOP 1 NULL
    FROM Table2 t2
    WHERE t1.ID = t2.ID
)
于 2016-12-20T13:42:33.953 に答える
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
于 2015-12-08T21:17:50.577 に答える