MySQL を使用して、ドキュメント「リエゾン」を持っていないすべてのユーザーをリストしたいと思います。これは、文書をまったく持っていないユーザー、または文書を持っているがこれらの文書に「連絡」していないユーザーを意味する可能性があります。
MySQL Query を使用するにはどうすればよいですか? うまくいかない!
これが(単純な)モデルです
Users (id, name)
Documents (id, user_id, name, path)
探している正しいクエリは次のとおりです。
SELECT
*
FROM
Users
WHERE
id NOT IN (
SELECT
user_id
FROM
Documents
WHERE
name = "liaison"
)
これにより、探している正確な結果が得られます。特定のユーザーがドキュメントを持っていない場合は、リストに表示されます。多くの文書があり、そのうちの 1 つが「リエゾン」である場合、リストには表示されません。
ドキュメントの名前で「liaison」を検索する場合は、 を に置き換えname = "liaison"
ますname LIKE "%liaison%"
。
基本的には、「リエゾン」という名前のドキュメントが指定されていないなど、すべてのユーザーを選択します。
これNOT EXISTS
は実行可能なソリューションです。別の方法として、大規模なセットでは、「anti JOIN」操作を使用するとパフォーマンスが向上することがあります。
SELECT u.*
FROM Users u
LEFT
JOIN (SELECT d.user_id
FROM Documents d
WHERE d.name = 'liaison'
) l
ON l.user_id = u.id
WHERE l.user_id IS NULL
としてエイリアス化されたインライン ビューl
は、'liaison' という名前のドキュメントを持つ user_id のリストを返します。その結果セットは Users テーブルに外部結合され、一致が見つかった行はすべて除外されます (l.user_id IS NULL のテスト)。
NOT EXISTS
これにより、述語を含むクエリに相当する結果セットが返されます。
もう 1 つの方法は、NOT IN
述語を含むクエリを使用することです。サブクエリが NULL を返さないことを保証する必要があるため、一般的なアプローチは、サブクエリによって返される列に IS NOT NULL 述語を含めることです。
SELECT u.*
FROM Users u
WHERE u.id NOT IN
( SELECT d.user_id
FROM Documents d
WHERE d.user_id IS NOT NULL
AND d.name = 'liaison'
)
私は次のようにNOT EXISTS
クエリを書きます:
SELECT u.*
FROM Users u
WHERE NOT EXISTS
( SELECT 1
FROM Documents d
WHERE d.name = 'liaison'
AND d.user_id = u.id
)
私の個人的な好みは、その相関サブクエリの SELECT リストでリテラル 1 を使用することです。クエリが 1 行の存在を探しているだけであることを思い出します。)
繰り返しますが、私は通常、「anti-join」パターンが大規模なセットで最高のパフォーマンスを発揮することを発見しました。(各ステートメントの EXPLAIN 出力を確認し、それぞれのパフォーマンスを測定して、状況に最適なステートメントを判断する必要があります。)
だから、私はついにうまくいくように見えるこの解決策を思いついた:
SELECT * FROM users u WHERE id NOT IN (SELECT DISTINCT user_id FROM user_documents WHERE name = 'LIAISON') ORDER BY c.lastname, c.firstname
SELECT users.*
FROM users left join Documents
on users.id = Documents.user_id
and documents.name='LIAISON'
WHERE documents.user_id is null
select * from Users where not exists (select id from Documents where Users.id = Documents.id and Documents.name = 'liaison')
試す :
SELECT DISTINCT u.*
FROM users u LEFT JOIN documents d ON d.user_id = u.id
WHERE d.id IS NULL OR d.name NOT LIKE '%liaison%'
「liaison」がドキュメントの正確な名前である場合は、パーセント記号を削除します。