Как я могу оптимизировать SQL-запрос - PullRequest
0 голосов
/ 16 сентября 2018

Я новичок в программировании, исходя из опыта бухгалтерского учета.У меня есть этот запрос, который я написал, который работает, но очень медленно.Мне интересно, есть ли способ, которым я мог бы написать это, чтобы оптимизировать его скорость.

Таблицы, из которых я получаю:

Мастер-таблица

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;

Ответы [ 3 ]

0 голосов
/ 16 сентября 2018

Запрос должен быть полностью оптимизирован. Я упомянул кое-что для оптимизации:

  1. использовать перекрестное применение вместо подзапросов
  2. использовать оконные функции
  3. также вы можете создать несколько индексов

Вы можете искать темы в Интернете. или вы можете задать свои вопросы.

0 голосов
/ 16 сентября 2018

Лучший подход в нашем случае - агрегировать перед выполнением объединений.У вас есть четыре различных агрегата, которые вам нужны:

  • master по pUnitName
  • master по WardName
  • accreditation по pUnitName
  • res от 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,Не ясно, что вы действительно хотите для этих столбцов.Вам может потребоваться сделать следующее:

  • Удалить mw.Num_Poll_Units и mw.reportedpu из GROUP BY.
  • Изменить SELECT на SUM(mw.Num_Poll_Units) или AVG(mw.Num_Poll_Units)или любую другую подходящую функцию.
0 голосов
/ 16 сентября 2018

Запрос довольно сложный, но в первую очередь я бы попытался поместить все эти подзапросы в один подзапрос следующим образом:

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 из таблицы res всего один раз и вычислить сумму для каждого условия, которое вы хотите. Кроме того, безусловно, должна быть возможность удалить это условие pUnitName из подзапроса, но для этого нужно больше знаний о вашем наборе данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...