特定の紹介会社から紹介されたクライアントから生成された新しいケース (ジョブ) の詳細を収集するために使用する SQL クエリ (MySQL) があります。重要なのは、クライアントの最初のケースである場合のみを選択する必要があることです。そうしないと、繰り返しクライアントが何度も参照されていると登録され、取得しようとしているものではありません。私たちのシステムにはクライアントとケースのテーブルがあり、それらは m:n テーブル (実際には 1:n のみ) で接続されているため、ケースと対応するクライアントを関連付けるために使用されます。
クライアントの最初のケースである場合にのみ値を返すという要件は、私に問題を引き起こしています。そのために、WHERE 句にサブクエリを用意し、特定のケースがクライアントの最初のものかどうかを、そのクライアントによる他のケースを探すことで確認します。これにより正しい出力が得られますが、クエリの実行が非常に遅くなり、どうすればよいかわかりません。そのため、より良い方法を見つけるために StackOverflow に頼っています。そのサブクエリを削除すると、すぐに実行されます。サブクエリを変更して、NOT EXISTS の代わりに COUNT(*) = 0 をチェックしようとしました。また、以前のケース作成日をチェックする代わりに、それよりも小さい case_ids をチェックするように変更しました。私は他のことを微調整しようとしましたが、いずれの場合も同様の遅い結果が得られました (~45 秒対インスタント)。依存サブクエリにならないように作り直す方法がわかりません。
注: 最初のケースが必要なので、複数のケースがあるクライアントを除外することはできません。私はできません
クエリを単純化するつもりでしたが、EXPLAIN の結果でそれがどのように表示されるかを理解し、それらを変更する必要があることに気付いたので、変更しませんでした。クライアントと連絡先テーブルがあり、連絡先はクライアントの子であり、連絡先はケースのあるもので、参照された値が保存されていますが、以前にケースがあったかどうかを判断する目的でクライアントに移動します。
1を試してください:
SELECT c2.case_id AS Case_ID, [other stuff]
FROM client_contact_cases c1 LEFT JOIN cases c2 ON (c1.case_id = c2.case_id)
LEFT JOIN client_contact c3 ON (c1.client_contact_id = c3.client_contact_id)
WHERE c2.case_created_date > '2013-05-01 00:00:00' AND c2.case_created_date < '2013-10-31 23:59:59'
AND c3.refer_by = 'Referring Partner #1'
AND NOT EXISTS (
SELECT c2_a.case_id FROM client_contact_cases c1_a LEFT JOIN cases c2_a ON (c1_a.case_id = c2_a.case_id)
WHERE c1_a.client_id = c1.client_id AND c2_a.case_created_date < c2.case_created_date
)
ORDER BY Case_ID ASC
説明結果:
'1', 'PRIMARY', 'c3', 'ALL', 'PRIMARY', NULL, NULL, NULL, '29340', 'Using where; Using temporary; Using filesort'
'1', 'PRIMARY', 'c1', 'ref', 'client_has_cases_FKIndex1,client_contact_has_cases_FKIndex2', 'client_has_cases_FKIndex1', '4', 'prod1_cases_clients.c3.client_contact_id', '1', 'Using index'
'1', 'PRIMARY', 'c2', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'prod1_cases_clients.c1.case_id', '1', 'Using where'
'2', 'DEPENDENT SUBQUERY', 'c1_a', 'index', 'client_contact_has_cases_FKIndex2', 'client_contact_has_cases_FKIndex2', '4', NULL, '33682', 'Using where; Using index'
'2', 'DEPENDENT SUBQUERY', 'c2_a', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'prod1_cases_clients.c1_a.case_id', '1', 'Using where'
サブクエリを次のように変更した場合の EXPLAIN の結果は次のとおりです。
...SELECT c1_a.case_id FROM client_contact_cases c1_a
WHERE c1_a.client_id = c1.client_id AND c1_a.case_id < c2.case_id
説明:
'1', 'PRIMARY', 'c3', 'ALL', 'PRIMARY', NULL, NULL, NULL, '29340', 'Using where; Using temporary; Using filesort'
'1', 'PRIMARY', 'c1', 'ref', 'client_contact_has_cases_FKIndex1,client_contact_has_cases_FKIndex2', 'client_contact_has_cases_FKIndex1', '4', 'prod1_cases_clients.c3.client_contact_id', '1', 'Using index'
'1', 'PRIMARY', 'c2', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'prod1_cases_clients.c1.case_id', '1', 'Using where'
'2', 'DEPENDENT SUBQUERY', 'c1_a', 'ALL', 'client_contact_has_cases_FKIndex2', NULL, NULL, NULL, '33682', 'Range checked for each record (index map: 0x4)'
「レコードごとにチェックされる範囲 (インデックス マップ: 0x4)」はどうなっていますか? すべてにインデックスが必要です。どんな助けでも大歓迎です!