提高查询效率

时间:2012-09-04 08:55:35

标签: mysql sql

我在mysql中为报告工具编写了以下查询。

这是一个内联选择。查询给出了正确的结果,但需要很长时间才能运行。有人可以建议任何替代方式或编写查询以使其更有效。

SELECT z.name1, (
       SELECT COUNT( AES_DECRYPT( l.answertext,  "aaa" ) ) 
       FROM household_data l
       INNER JOIN sms_household m 
             ON l.prim_key = m.hhid
       INNER JOIN sms_psu n 
             ON n.psu = m.psu
             AND n.state = m.state
             AND n.district = m.district
       INNER JOIN (
             SELECT p.prim_key, p.fieldname
             FROM household_data p
             WHERE p.basicname =  'Q05'
             AND AES_DECRYPT( p.answertext,  "aaa" ) =2
       ) women 
             ON l.prim_key = women.prim_key
             AND SUBSTR( l.fieldname, 5, 1 ) = SUBSTR( women.fieldname, 5, 1 ) 
             WHERE l.basicname =  'Q08' AND AES_DECRYPT( l.answertext,  "aaa" ) = 14
             AND z.psu = n.psu
             [AND n.state IN ( {state} )] 
             [AND n.district IN ( {district} )]
) female14, (
       SELECT COUNT( AES_DECRYPT( l.answertext,  "aaa" ) ) 
       FROM household_data l
       INNER JOIN sms_household m ON l.prim_key = m.hhid
       INNER JOIN sms_psu n 
             ON n.psu = m.psu
             AND n.state = m.state
             AND n.district = m.district
       INNER JOIN (
             SELECT p.prim_key, p.fieldname
             FROM household_data p
             WHERE p.basicname =  'Q05'
             AND AES_DECRYPT( p.answertext,  "aaa" ) =2
       ) women 
             ON l.prim_key = women.prim_key
             AND SUBSTR( l.fieldname, 5, 1 ) = SUBSTR( women.fieldname, 5, 1 ) 
             WHERE l.basicname =  'Q08' AND AES_DECRYPT( l.answertext,  "aaa" ) = 15
             AND z.psu = n.psu
             [AND n.state IN ( {state} )] 
             [AND n.district IN ( {district} )]
) female15, (
       SELECT COUNT( AES_DECRYPT( l.answertext,  "aaa" ) ) 
       FROM household_data l
       INNER JOIN sms_household m 
             ON l.prim_key = m.hhid
       INNER JOIN sms_psu n 
             ON n.psu = m.psu
                    AND n.state = m.state
                           AND n.district = m.district
       INNER JOIN (
             SELECT p.prim_key, p.fieldname
             FROM household_data p
             WHERE p.basicname =  'Q05'
             AND AES_DECRYPT( p.answertext,  "aaa" ) =2
       ) women 
             ON l.prim_key = women.prim_key
             AND SUBSTR( l.fieldname, 5, 1 ) = SUBSTR( women.fieldname, 5, 1 ) 
       WHERE l.basicname =  'Q08' AND AES_DECRYPT( l.answertext,  "aaa" ) =16
       AND z.psu = n.psu
       [AND n.state IN ( {state} )] 
       [AND n.district IN ( {district} )]
) female16, (
       SELECT count(AES_DECRYPT(household_data.answertext , "aaa")) * 100 / (
              SELECT count(AES_DECRYPT(household_data.answertext , "aaa"))
              FROM household_data 
              INNER JOIN sms_household
              INNER JOIN sms_psu
                    ON sms_psu.psu = sms_household.psu
                    AND sms_psu.state = sms_household.state
                    AND sms_psu.district = sms_household.district
              WHERE  basicname = 'Q07_year' AND z.psu= sms_psu.psu
              [AND sms_psu.state IN ( {state} )] 
              [AND sms_psu.district IN ( {district} )]
              )
       FROM household_data 
       INNER JOIN sms_household
       INNER JOIN sms_psu
             ON sms_psu.psu = sms_household.psu
             AND sms_psu.state = sms_household.state
             AND sms_psu.district = sms_household.district
       WHERE AES_DECRYPT(household_data.answertext , "aaa") = 9998 
       AND basicname = 'Q07_year'
       AND z.psu = sms_psu.psu
       [AND sms_psu.state IN ( {state} )] 
       [AND sms_psu.district IN ( {district} )]
) PercYearDontKnow
FROM household_data x
INNER JOIN sms_household y 
      ON x.prim_key = y.hhid
INNER JOIN sms_psu z 
      ON y.psu = z.psu
AND z.state = y.state
AND z.district = y.district
WHERE 1=1 
[AND y.state IN ( {state} )] 
[AND y.district IN ( {district} )
GROUP BY z.psu

2 个答案:

答案 0 :(得分:1)

我编辑了您的帖子,使您的查询结构更加清晰。我建议您在自己的代码中执行相同的操作。

重组后,很明显你正在重复一些查询以找到female14,female15和female16。

也许您应该为该部分单独查询,如下所示:

   SELECT n.name1, 
          n.psu, 
          AES_DECRYPT( l.answertext,  "aaa" ) AS answer, 
          COUNT(*) as count
   FROM household_data l
   INNER JOIN sms_household m 
         ON l.prim_key = m.hhid
   INNER JOIN sms_psu n 
         ON n.psu = m.psu
         AND n.state = m.state
         AND n.district = m.district
   INNER JOIN (
         SELECT p.prim_key, p.fieldname
         FROM household_data p
         WHERE p.basicname =  'Q05'
         AND AES_DECRYPT( p.answertext,  "aaa" ) =2
   ) women 
         ON l.prim_key = women.prim_key
         AND SUBSTR( l.fieldname, 5, 1 ) = SUBSTR( women.fieldname, 5, 1 ) 
         WHERE l.basicname =  'Q08' 
         AND AES_DECRYPT( l.answertext,  "aaa" ) = 14
         [AND n.state IN ( {state} )] 
         [AND n.district IN ( {district} )]
   GROUP BY n.psu, AES_DECRYPT( l.answertext,  "aaa" )

该查询应该为您提供Q08答案及其编号的摘要。

然后,您可以为PercYearDontKnow创建单独的查询。我相信之后重新组装数据仍然会比frankenquery更快。或者,将上述查询编码为SQL视图,并将其组合到更大的查询中。

顺便说一下,您可以使用COUNT( AES_DECRYPT( l.answertext, "aaa" ) )而不是COUNT(*)。这意味着将更少地调用解密函数。

另一个选择是SELECT AES_ENCRYPT( "2", "aaa" )并在比较Q08时将该值用作常量。这样,每个字段都不需要重复解密。

之后,我会按照另一个答案中给出的优化建议,特别是查看执行路径,看看是否需要添加索引。

答案 1 :(得分:0)

丑陋的......我的建议:

当然,在测试环境中做所有这些,而不是生产,它可能是凌乱的。 另一个建议,一次一步,检查每个小修改,以确保结果仍然相同。保存结果进行比较,最后获得好结果。