mysql - 如何优化sql查询

标签 mysql sql

我是一名编程新手,具有会计背景。我有我写的这个查询,它有效但很慢。我想知道是否有一种方法可以编写它来优化它的速度。

我正在获取的表:

主表

enter image description here

事件表 enter image description here

结果表 enter image description here

认证表 enter image description here

这里是查询:

SELECT a.lgName AS lgname
  , a.wardName AS wardName
  , a.pUnitName AS pUnitName
  , SUM(a.pvc_collected) AS pvc
  , SUM(a.voter_reg_no) AS purvs
  , (   SELECT COUNT(pUnitName)
        FROM master
        WHERE wardName = a.wardName) AS No_Poll_Unitss
  , (   SELECT COUNT(reportedpu)
        FROM master
        WHERE wardName = a.wardName
        AND reportedpu = 1) AS reportedpu
  , (   SELECT COUNT(pUnitName)
        FROM master
        WHERE pUnitName = a.pUnitName) AS No_Poll_Unitss
  , (   SELECT COUNT(reportedpu)
        FROM master
        WHERE pUnitName = a.pUnitName
        AND reportedpu = 1) AS reportedpu
  , (   SELECT SUM(total)
        FROM accreditation
        WHERE pu_name IN (   SELECT pUnitName
                             FROM master
                             WHERE pUnitName = a.pUnitName)) AS acr
  , (   SELECT SUM(cno)
        FROM res
        WHERE pUnitName IN (   SELECT pUnitName
                               FROM master
                               WHERE pUnitName = a.pUnitName)
        AND category = 'tvc') AS tvc
  , (   SELECT SUM(cno)
        FROM res
        WHERE pUnitName IN (   SELECT pUnitName
                               FROM master
                               WHERE pUnitName = a.pUnitName)
        AND category = 'apc') AS apc
  , (   SELECT SUM(cno)
        FROM res
        WHERE pUnitName IN (   SELECT pUnitName
                               FROM master
                               WHERE pUnitName = a.pUnitName)
        AND category = 'ivc') AS ivc
  , (   SELECT SUM(cno)
        FROM res
        WHERE pUnitName IN (   SELECT pUnitName
                               FROM master
                               WHERE pUnitName = a.pUnitName)
        AND category = 'pdp') AS pdp
  , (   SELECT SUM(cno)
        FROM res
        WHERE pUnitName IN (   SELECT pUnitName
                               FROM master
                               WHERE pUnitName = a.pUnitName)
        AND category = 'lp') AS lp
  , (   SELECT SUM(cno)
        FROM res
        WHERE pUnitName IN (   SELECT pUnitName
                               FROM master
                               WHERE pUnitName = a.pUnitName)
        AND category = 'adc') AS adc
  , (   SELECT SUM(cno)
        FROM res
        WHERE pUnitName IN (   SELECT pUnitName
                               FROM master
                               WHERE pUnitName = a.pUnitName)
        AND category = 'sdp') AS sdp
  , (   SELECT SUM(cno)
        FROM res
        WHERE pUnitName IN (   SELECT pUnitName
                               FROM master
                               WHERE pUnitName = a.pUnitName)
        AND category = 'adp') AS adp
  , (   SELECT SUM(cno)
        FROM res
        WHERE pUnitName IN (   SELECT pUnitName
                               FROM master
                               WHERE pUnitName = a.pUnitName)
        AND category = 'other') AS oth
FROM master AS a
GROUP BY a.pUnitName, a.userCode
ORDER BY a.userCode ASC;

最佳答案

在我们的案例中,最好的方法是在执行连接之前聚合。您需要四种不同的聚合:

  • master by pUnitName
  • master by WardName
  • 认证 pUnitName
  • res by pUnitName`

然后 LEFT JOIN 把它们放在一起:

SELECT m.pUnitName, m.userCode,
       SUM(m.pvc_collected) as pvc,
       SUM(m.voter_reg_no) AS purvs,
       mw.Num_Poll_Units, mw.reportedpu,
       mu.Num_Poll_Units, mu.reportedpu,
       a.acr,
       r.tvc, r.apc, . . .
FROM master m LEFT JOIN
     (SELECT m2.wardName, COUNT(*) as Num_Poll_Units,
             SUM(m2.reportedpu = 1) as reportedpu
      FROM master m2
      GROUP BY m2.wardName
     ) mw
     USING (wardname) LEFT JOIN
     (SELECT m2.pUnitName, COUNT(*) as Num_Poll_Units,
             SUM(m2.reportedpu = 1) as reportedpu
      FROM master m2
      GROUP BY m2.pUnitName
     ) mu
     USING (pUnitName) LEFT JOIN
     (SELECT a.pu_name, SUM(a.total) as acr
      FROM accreditation a
      GROUP BY a.pu_name
     ) a
     ON a.pu_name = m.pUnitName LEFT JOIN
     (SELECT r.pUnitName,
             SUM(CASE WHEN category = 'tvc' THEN cno ELSE 0 END) as tvc,
             SUM(CASE WHEN category = 'apc' THEN cno ELSE 0 END) as apc,
             . . .
      FROM res r
      GROUP BY r.pUnitNmae
     ) r
     USING (pUnitName)
GROUP BY m.pUnitName, m.userCode,
         mw.Num_Poll_Units, mw.reportedpu,
         mu.Num_Poll_Units, mu.reportedpu,
         a.acr,
         r.tvc, r.apc, . . .
ORDER BY m.userCode ASC;

注意:最外层查询不是按 WardName 聚合。目前尚不清楚您对这些列的真正需求。您可能需要执行以下操作:

  • GROUP BY 中删除 mw.Num_Poll_Unitsmw.reportedpu
  • SELECT 更改为 SUM(mw.Num_Poll_Units)AVG(mw.Num_Poll_Units) 或应使用任何适当的函数。

关于mysql - 如何优化sql查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52352551/

相关文章:

php - 数据库时区

sql - SQL : Force a value to be last in the order 中的按最后排序

mysql - 尝试编写复杂的查询来检索数据

php - jQuery ajax特殊字符问题

php - 回显从数据库中检索到的行的 session

php - 根据选定的 ID 通过 PHP 重定向用户

python - 需要在按不匹配日期分组的 2 个索引上转置一些 SQL 值(SQL 和 Python)

mysql - MYSQL如何让一条SELECT语句显示超过1000条记录?

mysql - 将 ID 链接到表 SQL 中的其他 ID

MySQL Count 和 Group By 两个不同的列