Mysql:別のテーブルにないテーブルから行を選択


118

別のテーブルに表示されない1つのテーブルのすべての行を選択する方法は?

表1:

+-----------+----------+------------+
| FirstName | LastName | BirthDate  |
+-----------+----------+------------+
| Tia       | Carrera  | 1975-09-18 |
| Nikki     | Taylor   | 1972-03-04 |
| Yamila    | Diaz     | 1972-03-04 |
+-----------+----------+------------+

表2:

+-----------+----------+------------+
| FirstName | LastName | BirthDate  |
+-----------+----------+------------+
| Tia       | Carrera  | 1975-09-18 |
| Nikki     | Taylor   | 1972-03-04 |
+-----------+----------+------------+

Table2にないTable1の行の出力例:

+-----------+----------+------------+
| FirstName | LastName | BirthDate  |
+-----------+----------+------------+
| Yamila    | Diaz     | 1972-03-04 |
+-----------+----------+------------+

多分このようなものがうまくいくはずです:

SELECT * FROM Table1 WHERE * NOT IN (SELECT * FROM Table2)

回答:


96

別のコメントで述べたように300列があり、すべての列を比較したい場合(列がすべて同じ名前であると想定)、a NATURAL LEFT JOINを使用して、2つのテーブル間で一致するすべての列名を暗黙的に結合して、手作業ですべての結合条件を入力する必要はありません。

SELECT            a.*
FROM              tbl_1 a
NATURAL LEFT JOIN tbl_2 b
WHERE             b.FirstName IS NULL

これは、列にNULL値がない場合にのみ期待どおりに機能することに注意してください。MySQLではNULL!= NULLなので、2番目のテーブルに重複する行がある場合でも、NULL値を持つすべての行が返されます。
カイル・コチス

84
300列ある場合は、データベースを再設計する必要があります。
Iharob Al Asimi 2016

ねえ、これは私にも有効です、ありがとう!しかし、上記のように行が300を超える場合は問題でしょうか?
thekucays

たとえば、クエリbtw .. "where b.FirstName is null"を "where b.LastName is null"に変更するとどうなりますか?違いは何ですか?これを聞いてごめんなさい、私はまだsqlが初めてです:D
thekucays

184

でなく、列名に基づいて副選択を行う必要があります*

たとえば、id両方のテーブルに共通のフィールドがある場合、次のようにできます。

SELECT * FROM Table1 WHERE id NOT IN (SELECT id FROM Table2)

その他の例については、MySQLサブクエリ構文を参照してください。


1
説明をありがとう!行のフィールドのバリエーションに興味があるので、行の選択をフィールドに

比較する列が数個しかない場合は、@ Steveの例に従って結合を行うことができます。多くの列を持つ2つのテーブルのデータの一般的な比較を実際に求めている場合は、MySQL diffツールを探したいと思うでしょう。
ステニー

2
Table2で表示している列にnullが含まれている場合、これは常に空のセットを返すことに注意してください。主キーに基づいて実行している場合は問題ありませんが、他のコンテキストでこのクエリを使用しようとしている人には関係があります。
マークアメリー

4
しかし、ビッグデータについて話しているとしたらどうでしょう。たとえば、Table2には1億行が含まれていますか?
農作物

賢くて賢い答え。どうも
Anjanaシルバ

44
SELECT *
FROM Table1 AS a
WHERE NOT EXISTS (
  SELECT *
  FROM Table2 AS b 
  WHERE a.FirstName=b.FirstName AND a.LastName=b.Last_Name
)

EXISTS 手伝います...


2
良い回答です。大規模なデータセットには経済的です。
ekerner 2014

強い。大規模なデータセットのベストアンサー
Ian Chadwick

35

標準のLEFT JOINで問題を解決できる可能性があり、結合のフィールドにインデックスが付けられている場合は、
より高速になるはずです。

SELECT *
FROM Table1 as t1 LEFT JOIN Table2 as t2 
ON t1.FirstName = t2.FirstName AND t1.LastName=t2.LastName
WHERE t2.BirthDate Is Null

大丈夫、私はそれでなければならないことを推測します、ところでなぜのWHERE t2.Birthdate Is Null代わりにAND t1.Birthdate = t2.Birthdate

これを追加すると、すべての行が返されるため、出力では2番目のテーブルにない行のみが表示されると言う
Steve

1
Table2!のすべての行を返す必要がないため、これは素晴らしい答えです。
dotancohen 2013

私は同意します、素晴らしい答えです。私は4つのテーブルの間に多対多のテーブルを持っています。内部結合にANDを入れると、間違いなくより経済的になります。
DR。

6

試してください:

SELECT * FROM table1
    LEFT OUTER JOIN table2
    ON table1.FirstName = table2.FirstName and table1.LastName=table2.LastName
    WHERE table2.BirthDate IS NULL

4

この簡単なクエリを試してください。それは完全に動作します。

select * from Table1 where (FirstName,LastName,BirthDate) not in (select * from Table2);


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