データベースアプリケーションのメンテナンス作業をしていますが、あるテーブルからの値が外部キーのスタイルで使用されていても、テーブルに外部キーの制約がないことが喜びです。
これらの列にFK制約を追加しようとしていますが、これまでのエラーによるテーブル内の不良データが既に大量にロードされているため、単純に修正されていない行を見つける必要があります。他のテーブルと一致させてから削除してください。
私はウェブ上でこの種のクエリのいくつかの例を見つけましたが、それらはすべて説明よりもむしろ例を提供するように思われます、そして私はそれらがなぜ働くのかわかりません。
他のテーブルで一致しないすべての行を返すクエリを作成する方法、およびその処理を説明することで、すべての人に対してSOを実行するのではなく、自分で作成できるようになります。このテーブルが混乱しているFK制約はありませんか?
これは簡単なクエリです。
SELECT t1.ID
FROM Table1 t1
LEFT JOIN Table2 t2 ON t1.ID = t2.ID
WHERE t2.ID IS NULL
重要な点は次のとおりです。
LEFT JOIN
が使用されています。 Table1
に一致する行があるかどうかにかかわらず、これはTable2
からすべての行を返します。
WHERE t2.ID IS NULL
句。これは、Table2
から返されたIDがnullである行だけに返される結果を制限します - 言い換えれば、そのためのTable2
にNOレコードがありますTable1
からの特定のID。 Table2.ID
は、IDがTable1
で一致しないTable2
からのすべてのレコードに対してNULLとして返されます。
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)
SELECT id FROM table1 WHERE foreign_key_id_column NOT IN (SELECT id FROM table2)
表1には外部キー制約を追加する列がありますが、表2のforeign_key_id_column
の値がすべてid
と一致するわけではありません。
id
sをリストします。これらが削除したい行になります。NOT IN
文節は、foreign_key_id_column
の値が表2 id
sのリストにない行だけに照会を制限します。SELECT
ステートメントは、表2にあるすべてのid
のリストを取得します。T2
は、制約を追加するテーブルです。
SELECT *
FROM T2
WHERE constrained_field NOT
IN (
SELECT DISTINCT t.constrained_field
FROM T2
INNER JOIN T1 t
USING ( constrained_field )
)
そして結果を削除してください。
今度は、給与が支払われていない従業員表のレコードが欲しいと思います。これを3つの方法で行うことができます。
select * from employee
where id not in(select e.id from employee e inner join salary s on e.id=s.id)
select * from employee e
left outer join salary s on e.id=s.id where s.id is null
select * from employee e
full outer join salary s on e.id=s.id where e.id not in(select id from salary)
ここからの同様の質問から 他のテーブルに存在しないレコードを取得するためのMySQLの内部結合クエリ これでうまくいく
SELECT * FROM bigtable
LEFT JOIN smalltable ON bigtable.id = smalltable.id
WHERE smalltable.id IS NULL
smalltable
は不足しているレコードがある場所、bigtable
はすべてのレコードがある場所です。クエリは、smalltable
には存在しないがbigtable
には存在するすべてのレコードをリストします。 id
を他の一致基準で置き換えることができます。
どちらが最適化されているのか(@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);
以下のようにビューを選ぶことができます。
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]