优化一个SQL查询

时间:2013-03-07 17:16:07

标签: mysql sql

我需要运行查询才能从数据库中获取一些数据。问题是我使用的查询有效但需要很长时间。

SELECT SHH1.CUST_NO,
       SHH1.CUST_NAME,
       ADDR.BVADDREMAIL 
FROM SALES_HISTORY_HEADER SHH1
INNER JOIN ADDRESS ADDR ON (SHH1.CUST_NO=ADDR.CEV_NO)
INNER JOIN CUSTOMER CUST ON (SHH1.CUST_NO=CUST.CUS_NO)
WHERE CUST.HOLD = 0
AND SHH1.CUST_NO IN (SELECT SHH2.CUST_NO 
                     FROM SALES_HISTORY_HEADER SHH2
                     GROUP BY SHH2.CUST_NO 
                     HAVING Max(SHH2.IN_DATE) < '20120101')
GROUP BY SHH1.CUST_NO,
         SHH1.CUST_NAME,
         ADDR.BVADDREMAIL

我不是很擅长这个,所以想知道你们有没有人可以帮助我?感谢。

5 个答案:

答案 0 :(得分:0)

我认为你不需要子选择。以下内容应该给你相同的结果:

SELECT SHH1.CUST_NO,SHH1.CUST_NAME,ADDR.BVADDREMAIL 
FROM SALES_HISTORY_HEADER SHH1
INNER JOIN ADDRESS ADDR ON (SHH1.CUST_NO=ADDR.CEV_NO)
INNER JOIN CUSTOMER CUST ON (SHH1.CUST_NO=CUST.CUS_NO)
WHERE CUST.HOLD = 0
GROUP BY SHH1.CUST_NO,SHH1.CUST_NAME,ADDR.BVADDREMAIL
HAVING Max(SHH1.IN_DATE) < '20120101'

答案 1 :(得分:0)

假设CUST_NAME上有CUSTOMER,请尝试:

SELECT CUST.CUS_NO CUST_NO,
       CUST.CUST_NAME,
       ADDR.BVADDREMAIL 
FROM CUSTOMER CUST
JOIN ADDRESS ADDR ON CUST.CUS_NO=ADDR.CEV_NO
LEFT JOIN SALES_HISTORY_HEADER SHH 
       ON CUST.CUS_NO=SHH.CUST_NO AND SHH.IN_DATE >= '20120101'
WHERE CUST.HOLD = 0 AND SHH.CUST_NO IS NULL
GROUP BY CUST.CUS_NO, ADDR.BVADDREMAIL 

答案 2 :(得分:0)

使用执行计划查询的哪一部分具有主要执行成本。这可能表明问题出在哪里。我要执行的下一步是检查索引创建。请回想一下,聚合索引是默认创建的PK,但是在FK上创建非聚集索引以及您可能特别感兴趣的任何潜在字段也是一种很好的做法。希望它有所帮助。

答案 3 :(得分:0)

我同意Mark Bannister's answer OP应该FROM CUSTOMER代替FROM SALES_HISTORY_HEADER

因此,假设CUST_NAME位于CUSTOMER,我会执行以下操作:

SELECT CUST.CUS_NO,
       CUST.CUST_NAME,
       ADDR.BVADDREMAIL 
FROM CUSTOMER CUST
JOIN ADDRESS ADDR ON CUST.CUS_NO = ADDR.CEV_NO
WHERE CUST.HOLD = 0
AND CUST.CUS_NO IN (SELECT SHH.CUST_NO 
                    FROM SALES_HISTORY_HEADER SHH
                    GROUP BY SHH.CUST_NO 
                    HAVING Max(SHH.IN_DATE) < '20120101')

请注意,subquery materialization必须处于活动状态才能优化子选择。

答案 4 :(得分:0)

在加入

之前删除一些行怎么样?
SELECT S.CUST_NO,
      ,S.Cust_NAME
      ,A.BVADDREMAIL
FROM CUSTOMER C
    INNER JOIN SALES_HISTORY_HEADER S ON (CUST.HOLD = 0 AND S.CUST_NO=C.CUS_NO)
        INNER JOIN ADDRESS A ON (S.CUST_NO=A.CEV_NO)
GROUP BY S.CUST_NO,S.CUST_NAME,A.BVADDREMAIL
HAVING Max(S.IN_DATE) < '20120101'

我对StevieG答案的更新