使用LEFT连接和Join上的条件进行更有效的SELECT查询

时间:2014-09-24 17:57:23

标签: mysql sql join

这个问题在the back of one I asked earlier today。答案我解决了我的问题,通过限制返回的行我可以看到它做我想要的。

但是现在当我尝试运行整个查询时,没有限制,目的是导出到excel进行分析,我似乎无法到达任何地方。因为MySQL工作台再次要求我输入密码并且查询停止运行,我开始使用SQL。我不确定这条信息是否是其他事情正在发生并且转移到我​​的真实问题中,这是"如果可以的话,如何让这个查询更快地运行?"目前它至少运行5分钟才开始使用#34;。

当我解释这里的查询是提供的内容:

1   SIMPLE  co  ALL                 185610  Using temporary; Using filesort
1   SIMPLE  my  ref PRIMARY PRIMARY 4   bm_emails.co.id 23  
1   SIMPLE  nvk eq_ref  PRIMARY PRIMARY 4   bm_emails.co.id 1   

据推测,临时表正在导致"使用临时表"是一个问题,但我不确定如何在维护我的查询时绕过它。 实际的查询在这里:

SELECT 
    co.email,
    nvk.nvk_medium,
    CAST(MIN(co.created) AS DATE) AS first_contact,
    MIN(CASE WHEN my.my_id = 581 THEN my.data END) AS WA_Created,
    MIN(CASE WHEN my.my_id = 3347 THEN my.data END) AS WA_Upgraded
FROM bm_emails.cid208 co
LEFT JOIN bm_emails.my208 my ON co.id = my.eid AND (my_id = 581 OR my_id = 3347)
LEFT JOIN bm_emails.nvk208 nvk ON nvk.eid = co.id
GROUP BY email

2 个答案:

答案 0 :(得分:1)

Union all通常比在连接条件下使用OR更快。检查数据结果,我认为内部联接可能使用UNON更有意义,但必须查看数据。我还想了解更多关于你想看到来自bm_emails.cid208的记录的更多信息,这些记录不会加入my_id 581或myid 3347的记录。

试试这个:

SELECT email,nvk_medium, CAST(MIN(created) AS DATE) AS first_contact,WA_Created,WA_Upgraded
FROM 
(
    SELECT 
        co.email,
        nvk.nvk_medium,
        co.created AS first_contact,
       my.data AS WA_Created,
       NULL AS WA_Upgraded
    FROM bm_emails.cid208 co
    LEFT JOIN bm_emails.my208 my ON co.id = my.eid AND my_id = 581 
    LEFT JOIN bm_emails.nvk208 nvk ON nvk.eid = co.id
    UNION ALL
    SELECT 
        co.email,
        nvk.nvk_medium,
        co.created AS first_contact,
       NULL AS WA_Created,
       my.data AS WA_Upgraded
    FROM bm_emails.cid208 co
    LEFT JOIN bm_emails.my208 my ON co.id = my.eid AND my_id = 3347
    LEFT JOIN bm_emails.nvk208 nvk ON nvk.eid = co.id
) a
GROUP BY email,nvk_medium,WA_Created,WA_Upgraded

我还会考虑CAST(MIN(已创建)AS DATE)是否应为Min(CAST(创建为AS DATE)),具体取决于创建字段的数据类型。如果是某种类型的基于字符串的字段,那么10/20/2014将小于2/24/2013并将被选中。如果它存储在日期时间类型的字段中并且您只是缩短了时间,那么这可以。

答案 1 :(得分:0)

如果我假设bm_emails每封电子邮件包含一行,那么这可能会更快:

select co.email,
       (select nvk.nvk_medium from bm_emails.nvk208 nvk where nvk.eid = co.id limit 1) as nvk_medium,
       co.created,
       (select min(my.data) from bm_emails.my208 my where co.id = my.eid and my.mid = 581) as WA_Created,
       (select min(my.data) from bm_emails.my208 my where co.id = my.eid and my.mid = 3347) as WA_Updated
from bm_emails.cid208 co;

这可以利用以下索引:

bm_emails.nvk208(eid, nvk_medium)
bm_emails.my208(eid, mid, data)

当然,这取决于第一个假设,即第一个表每封电子邮件有一行。

编辑:

即使有多封电子邮件,我仍会尝试这样做:

select cn.mail, cn.nvk_medium, cn.created,
       (select min(my.data) from bm_emails.my208 my where co.id = my.eid and my.mid = 581) as WA_Created,
       (select min(my.data) from bm_emails.my208 my where co.id = my.eid and my.mid = 3347) as WA_Updated
from (select co.email, nvk.nvk_medium, min(co.created) as created
      from bm_emails.cid208 co left join
           bm_emails.nvk208 nvk 
           on nvk.eid = co.id 
      group by co.email, nvk.nvk_medium
     ) cn;