0

我有一个 SQL 查询(MySQL),用于收集由特定推荐公司推荐的客户生成的新案例(工作)的详细信息。重要的是,我们只需要选择那些是客户的第一个案例,否则重复的客户会一遍又一遍地注册为被推荐,这不是我们想要得到的。在我们的系统中,我们有客户和案例表,它们通过一个 m:n 表连接(实际上只是 1:n),因此用于将案例与其对应的客户相关联。

仅在客户的第一种情况下返回值的要求给我带来了麻烦。为此,我在 WHERE 子句中有一个子查询,通过查找该客户端的任何其他情况来检查特定情况是否是客户端的第一个。这给出了正确的输出,但使查询运行得非常缓慢,我不知道该怎么做,这就是为什么我求助于 StackOverflow 来寻找更好的方法。如果我删除该子查询,它会立即运行。我尝试更改子查询以检查 COUNT(*) = 0 而不是 NOT EXISTS。我还对其进行了更改以检查任何较小的 case_ids,而不是检查较早的案例创建日期。我尝试过调整其他东西,在每种情况下我都得到了类似的缓慢结果(约 45 秒 vs 即时)。我不知道如何返工以使其不是依赖子查询。

注意:如果客户有多个案例,我不能排除他们,因为我需要第一个。我不能

我打算为您简化查询,但后来我意识到我还必须弄清楚 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)”是怎么回事?一切都应该有一个索引。任何帮助是极大的赞赏!

4

1 回答 1

0

啊哈,我想出了一个不依赖的子查询!相反,我正在检查子查询中客户的第一个案例列表中的 case_id。现在它运行不到半秒。我很想在此处的 WHERE 子句中添加一些内容以进一步减少它。我不能输入日期范围,因为它会阻止查询检查以前的案例并给我比它应该的结果略多的结果,但我后来确实添加了 c3_a.refer_by = 'Referring Partner #1'。

子查询现在是:

AND c2.case_id IN (
    SELECT MIN(c2_a.case_id)  
    FROM client_contact_cases c1_a LEFT JOIN cases c2_a ON (c1_a.case_id = c2_a.case_id) 
    GROUP BY c1_a.client_id
 ) 
于 2013-11-14T23:07:54.927 回答