web-dev-qa-db-ja.com

別のテーブルでエントリが一致しない行を選択する方法

データベースアプリケーションのメンテナンス作業をしていますが、あるテーブルからの値が外部キーのスタイルで使用されていても、テーブルに外部キーの制約がないことが喜びです。

これらの列にFK制約を追加しようとしていますが、これまでのエラーによるテーブル内の不良データが既に大量にロードされているため、単純に修正されていない行を見つける必要があります。他のテーブルと一致させてから削除してください。

私はウェブ上でこの種のクエリのいくつかの例を見つけましたが、それらはすべて説明よりもむしろ例を提供するように思われます、そして私はそれらがなぜ働くのかわかりません。

他のテーブルで一致しないすべての行を返すクエリを作成する方法、およびその処理を説明することで、すべての人に対してSOを実行するのではなく、自分で作成できるようになります。このテーブルが混乱しているFK制約はありませんか?

262
Frosty840

これは簡単なクエリです。

SELECT t1.ID
FROM Table1 t1
    LEFT JOIN Table2 t2 ON t1.ID = t2.ID
WHERE t2.ID IS NULL

重要な点は次のとおりです。

  1. LEFT JOINが使用されています。 Table1に一致する行があるかどうかにかかわらず、これはTable2からすべての行を返します。

  2. WHERE t2.ID IS NULL句。これは、Table2から返されたIDがnullである行だけに返される結果を制限します - 言い換えれば、そのためのTable2NOレコードがありますTable1からの特定のID。 Table2.IDは、IDがTable1で一致しないTable2からのすべてのレコードに対してNULLとして返されます。

497
AdaTheDev

EXISTS 式を使うのがより強力です。つまり、LEFT JOINの場合は結合したい行をもっと正確に選ぶことができます。結合テーブルの内容すべてその効率は、nullテストのLEFT JOINの場合とおそらく同じです。

SELECT t1.ID
FROM Table1 t1
WHERE NOT EXISTS (SELECT t2.ID FROM Table2 t2 WHERE t1.ID = t2.ID)
60
Ondrej Bozek
SELECT id FROM table1 WHERE foreign_key_id_column NOT IN (SELECT id FROM table2)

表1には外部キー制約を追加する列がありますが、表2のforeign_key_id_columnの値がすべてidと一致するわけではありません。

  1. 最初の選択は、table1からのidsをリストします。これらが削除したい行になります。
  2. WhereステートメントのNOT IN文節は、foreign_key_id_columnの値が表2 idsのリストにない行だけに照会を制限します。
  3. 括弧内のSELECTステートメントは、表2にあるすべてのidのリストを取得します。
10
Theo Voss

T2は、制約を追加するテーブルです。

SELECT *
FROM T2
WHERE constrained_field NOT
IN (
    SELECT DISTINCT t.constrained_field
    FROM T2 
    INNER JOIN T1 t
    USING ( constrained_field )
)

そして結果を削除してください。

7
Karel

次の2つのテーブル(給与と従業員)があるとします enter image description here

今度は、給与が支払われていない従業員表のレコードが欲しいと思います。これを3つの方法で行うことができます。

  1. 内部結合を使用する
select * from employee
where id not in(select e.id from employee e inner join salary s on e.id=s.id)

enter image description here

  1. 左外部結合の使用
select * from employee e 
left outer join salary s on e.id=s.id  where s.id is null

enter image description here

  1. 完全結合を使用する
select * from employee e
full outer join salary s on e.id=s.id where e.id not in(select id from salary)

enter image description here

3
Debendra Dash

ここからの同様の質問から 他のテーブルに存在しないレコードを取得するためのMySQLの内部結合クエリ これでうまくいく

SELECT * FROM bigtable 
LEFT JOIN smalltable ON bigtable.id = smalltable.id 
WHERE smalltable.id IS NULL

smalltableは不足しているレコードがある場所、bigtableはすべてのレコードがある場所です。クエリは、smalltableには存在しないがbigtableには存在するすべてのレコードをリストします。 idを他の一致基準で置き換えることができます。

1
Luis H Cabrejo

どちらが最適化されているのか(@AdaTheDevと比較して)わからないが、これを使用すると速くなるように思われる(少なくとも私には)

SELECT id FROM table_1 EXCEPT SELECT DISTINCT (table1_id) table1_id FROM table_2

他の特定の属性を取得したい場合は、次のものを使用できます。

SELECT COUNT(*) FROM table_1 where id in (SELECT id FROM table_1 EXCEPT SELECT DISTINCT (table1_id) table1_id FROM table_2);

0
Jerin K. John

以下のようにビューを選ぶことができます。

CREATE VIEW AuthorizedUserProjectView AS select t1.username as username, t1.email as useremail, p.id as projectid, 
(select m.role from userproject m where m.projectid = p.id and m.userid = t1.id) as role 
FROM authorizeduser as t1, project as p

次に、ビューを選択または更新するために作業します。

select * from AuthorizedUserProjectView where projectid = 49

これは、下の図に示すような結果になります。つまり、一致しない列の場合はnullが入力されています。

[Result of select on the view][1]
0
Nitesh singh