我是编程新手,来自会计背景。我已经写了这个查询,但效果非常慢。我想知道是否有一种方法可以优化它的速度。
我要从中获取的表:
主表
事件表
结果表
认证表
以下是查询:
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;
答案 0 :(得分:1)
查询是非常棘手的,但是我想尝试的第一件事是以这种方式将所有这些子查询放入一个子查询中:
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;
这应该只运行一次从res表中进行选择,并为每个所需条件计算总和。另外,从子查询中删除该pUnitName条件当然应该是可能的,但是它需要更多有关数据集的知识。
答案 1 :(得分:1)
在我们的案例中,最好的方法是在进行连接之前先汇总 。您需要四种不同的聚合:
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)
或使用任何适当的功能。答案 2 :(得分:0)
查询必须完全优化。我提到了一些使其优化的点:
您可以在Internet上搜索主题。 或者你可以问你的问题。