Mysql 如何优化sql查询

Mysql 如何优化sql查询,mysql,sql,Mysql,Sql,我是编程新手,有会计背景。我写了一个问题,但很慢。我想知道是否有一种方法我可以写它来优化它的速度 我从中获取的表格: 主表 事件表 结果表 认证表 以下是查询: 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 COU

我是编程新手,有会计背景。我写了一个问题,但很慢。我想知道是否有一种方法我可以写它来优化它的速度

我从中获取的表格:

主表

事件表

结果表

认证表

以下是查询:

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;

查询相当棘手,但我要尝试的第一件事是以这种方式将所有这些子查询放在一个子查询中:

SELECT *
FROM master AS A
CROSS JOIN (   SELECT SUM(IF(category = 'adp', cno, 0)) AS adp
                 -- All other conditions
                 , SUM(IF(category = 'other', cno, 0)) AS other
               FROM res AS R
               WHERE pUnitName IN (   SELECT pUnitName
                                      FROM master
                                      WHERE pUnitName = A.pUnitName)
               AND category = 'other') AS oth;

这应该只运行一次select from res table,并为您想要的每个条件计算sum。此外,当然可以从子查询中删除pUnitName条件,但它需要更多关于数据集的知识。

必须完全优化查询。我提到了一些使其优化的要点:

  • 使用交叉应用代替子查询
  • 使用窗口功能
  • 还可以创建一些索引
  • 您可以在internet上搜索主题。
    或者你可以问你的问题。

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

    • master
      by
      pUnitName
    • master
      by
      WardName
    • 认证
      by
      pUnitName
    • res
      由pUnitName提供`
    然后
    左键将它们连接在一起:

    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
    聚合的。目前还不清楚这些列真正需要什么。您可能需要执行以下操作:

    • mw.Num\u Poll\u装置
      mw.reportedpu
      组中移除
    • SELECT
      更改为
      SUM(mw.Num\u Poll\u Units)
      AVG(mw.Num\u Poll\u Units)
      或应使用的任何适当功能

    您需要为当前查询提供相关的表结构、尝试实现的内容、一些示例数据、预期输出和
    解释
    语句结果!从第一眼看,这个查询是不好的,因为子查询太多,每行可能运行多次。因此,根据您的需求,可以提出完全不同的解决方案@MadhurBhaiya,我已经做到了。