2017-10-15 202 views
0

我试图优化这个MySQL查询,我想知道当前约会之前没有预约的客户数量,换句话说,if他们有一个约会(这是什么NOT IN(子查询正在检查),然后排除它们。)优化一个MySQL NOT IN(查询

但是,这个查询是绝对杀死性能。我知道,MySQL不是非常好的查询,但我无法确定优化此查询的最佳方式,它需要15到30秒的时间才能运行,我已在CustNo,AptStatus和AptNum上创建了索引

SELECT 
     COUNT(*)    AS NumOfCustomersWithPriorAppointment, 
FROM 
     transaction_log AS tl 
LEFT JOIN 
     appointment AS a 
ON 
     a.AptNum = tl.AptNum 
INNER JOIN 
     customer AS c 
ON 
     c.CustNo = tl.CustNo 
WHERE 
     a.AptStatus IN (2) 
AND  a.CustNo NOT IN 
     (
       SELECT 
         a2.CustNo 
       FROM 
         appointment a2 
       WHERE 
         a2.AptDateTime < a.AptDateTime) 


AND  a.AptDateTime > BEGIN_QUERY_DATE 
AND  a.AptDateTime < END_QUERY_DATE 

预先感谢您。

+0

请为您的查询中的每个表提供'SHOW CREATE TABLE'语句。 –

+0

BEGIN_QUERY_DATE是常量吗?或另一列?用'LEFT JOIN .. IS NULL'重写查询;告诉我们它是否更快。 –

+0

顺便提一下,你的外部连接(a)实际上是一个内部连接 – Strawberry

回答

0

尝试以下操作:

SELECT 
     COUNT(*)    AS NumOfCustomersWithPriorAppointment, 
FROM 
     transaction_log AS tl 
INNER JOIN 
     appointment AS a 
ON 
     a.AptNum = tl.AptNum 
LEFT OUTER JOIN appointment AS earlier_a 
     ON earlier_a.CustNo = a.CustNo 
     AND earlier_a.AptDateTime < a.AptDateTime 
INNER JOIN 
     customer AS c 
ON 
     c.CustNo = tl.CustNo 
WHERE 
     a.AptStatus IN (2) 
AND  earlier_a.AptNum IS NULL 


AND  a.AptDateTime > BEGIN_QUERY_DATE 
AND  a.AptDateTime < END_QUERY_DATE 

这将从一个综合指数受益于(CustNo,AptDateTime)。使其具有唯一性,如果适合你的商业模式(逻辑上似乎像它应该的,但实际上它可能不会,这取决于你如何处理冲突在您的应用程序。)

提供SHOW CREATE TABLE报表中的所有表如果不创建充分的性能改进。

+0

这个查询确切地指明了它。非常感谢您的帮助和建议! – 3C41DC