我有一个案例需要从包含大量汇总数据的表中收集销售统计信息。该表有几百万个条目,数据库本身大约是22Gb。有大量数据可供使用!
我有这个工作查询,但我觉得我应该做得更好 - 而且它也很慢。
我在CentOS 7上使用带有sqlsrv扩展名的PHP连接到MSSQL数据库(ERP系统)。
此查询中的我的php变量设置如下:
$customer = '12345';
$year = '2016';
$compared_year = '2015';
因此,正如您可能已经猜到的那样,我正在为2016年和2015年的每个月收集特定客户的销售统计数据。
SELECT
ProdTr.CustNo AS customernummer,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $year . "01' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS sum_period_1,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $year . "02' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS sum_period_2,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $year . "03' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS sum_period_3,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $year . "04' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS sum_period_4,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $year . "05' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS sum_period_5,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $year . "06' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS sum_period_6,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $year . "07' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS sum_period_7,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $year . "08' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS sum_period_8,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $year . "09' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS sum_period_9,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $year . "10' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS sum_period_10,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $year . "11' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS sum_period_11,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $year . "12' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS sum_period_12,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $year . "01' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS dg_period_1,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $year . "02' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS dg_period_2,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $year . "03' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS dg_period_3,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $year . "04' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS dg_period_4,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $year . "05' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS dg_period_5,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $year . "06' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS dg_period_6,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $year . "07' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS dg_period_7,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $year . "08' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS dg_period_8,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $year . "09' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS dg_period_9,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $year . "10' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS dg_period_10,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $year . "10' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS dg_period_11,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $year . "11' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS dg_period_12,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "01' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_sum_period_1,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "02' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_sum_period_2,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "03' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_sum_period_3,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "04' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_sum_period_4,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "05' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_sum_period_5,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "06' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_sum_period_6,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "07' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_sum_period_7,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "08' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_sum_period_8,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "09' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_sum_period_9,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "10' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_sum_period_10,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "11' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_sum_period_11,
(SELECT SUM(DAm) AS 'Sum' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "12' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_sum_period_12,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "01' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_dg_period_1,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "02' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_dg_period_2,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "03' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_dg_period_3,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "04' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_dg_period_4,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "05' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_dg_period_5,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "06' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_dg_period_6,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "07' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_dg_period_7,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "08' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_dg_period_8,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "09' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_dg_period_9,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "10' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_dg_period_10,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "11' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_dg_period_11,
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM ProdTr WHERE AcYrPr = '" . $compared_year . "12' AND ProdTr.TrTp = 1 AND ProdTr.CustNo = '" . $customer . "') AS compared_dg_period_12
FROM ProdTr
WHERE AcYrPr LIKE 201612
AND ProdTr.TrTp = 1
AND ProdTr.CustNo = '" . $customer . "'
GROUP BY ProdTr.CustNo, ProdTr.TrTp, ProdTr.AcYrPr
请注意,查询效果很好,可以得到我期望的结果 - 但对于有很多订单/交易的客户来说,这个结果太慢了。
有关如何加快速度的任何指示?
非常感谢你的时间!
答案 0 :(得分:3)
您的查询应该使用条件聚合:
SELECT ProdTr.CustNo AS customernummer,
SUM(CASE WHEN AcYrPr = '" . $year . "01' THEN DAm ELSE 0 END) as sum_period_1,
SUM(CASE WHEN AcYrPr = '" . $year . "02' THEN DAm ELSE 0 END) as sum_period_2,
. . .
WHERE AcYrPr LIKE 201612 AND ProdTr.TrTp = 1 AND
ProdTr.CustNo = '" . $customer . "'
GROUP BY ProdTr.CustNo, ProdTr.TrTp;
不需要子查询。