0

I have written the following query in mysql for a reporting tool.

It is a inline select.The query gives me correct result but takes a long time to run. Can someone suggest any alternate way or writing the query to make it more efficient.

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
4

2 回答 2

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 时使用该值作为常数。这样,每个字段都不需要重复解密。

之后,我将遵循此处另一个答案中给出的优化建议,特别是查看执行路径以查看是否需要添加索引。

于 2012-09-04T09:52:19.983 回答
0

丑陋的……我的建议:

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

于 2012-09-04T09:07:08.000 回答