[英]How to optimize my query speed (avoid using subselect for every row)?
我有一个名为 CisLinkLoadedData 的表。 Is 有Distributor
、 Network
、 Product
、 DocumentDate
、 Weight
、 AmountCP
和Quantity
列。 它用于存储一些产品的日常销售。 AmountCP / Quantity
是产品在特定日期的价格。 有促销和定期销售,但没有标志。 我们可以通过比较它的价格与一个月内的最高记录价格来判断某个记录是常规的还是促销的。 我确实在这张照片上解释过。
我需要进行查询以显示每月某些产品的汇总常规和促销销售。 好吧,我做到了,但它非常慢(6 分钟执行 160 万条记录)。 我怀疑这是因为我使用子查询来确定每条记录的最高价格,但我不知道如何以另一种方式进行。
这是我做的:
SELECT
Distributor,
Network,
Product,
cast(month(DocumentDate) as VARCHAR) + '.' + cast(year(DocumentDate) as VARCHAR) AS MonthYear,
SUM(Weight) AS MonthlyWeight,
IsPromo
FROM (SELECT
main_clld.Distributor,
main_clld.Network,
main_clld.Product,
main_clld.DocumentDate,
main_clld.Weight,
main_clld.Quantity,
main_clld.AmountCP,
CASE WHEN (main_clld.AmountCP / main_clld.Quantity) < (SELECT MAX(sub_clld.AmountCP / NULLIF(sub_clld.Quantity, 0)) FROM CisLinkLoadedData AS sub_clld WHERE sub_clld.Distributor = main_clld.Distributor AND sub_clld.Network = main_clld.Network AND sub_clld.Product = main_clld.Product AND cast(month(sub_clld.DocumentDate) as VARCHAR) + '.' + cast(year(sub_clld.DocumentDate) as VARCHAR) = cast(month(main_clld.DocumentDate) as VARCHAR) + '.' + cast(year(main_clld.DocumentDate) as VARCHAR) AND sub_clld.Quantity > 0 AND sub_clld.GCRecord IS NULL) THEN 1 ELSE 0 END AS IsPromo
FROM CisLinkLoadedData AS main_clld
WHERE main_clld.Quantity > 0 AND main_clld.GCRecord IS NULL) AS bad_query
GROUP BY
Distributor,
Network,
Product,
cast(month(DocumentDate) as VARCHAR) + '.' + cast(year(DocumentDate) as VARCHAR),
IsPromo;
在这种情况下可以做什么? 顺便说一句,如果您可以使用类似的另一种结构( Distributor
、 Network
、 Product
、 MonthYear
、 RegularWeight
、 PromoWeight
)来制作结果表,那就更好了。 这是我最初尝试过的,但失败了。 我使用 Microsoft SQL Server。
您可以使用窗口函数而不是相关子查询来检索每组的最高价格(每个组由 partition by 子句定义):
MAX(main_clld.AmountCP / NULLIF(main_clld.Quantity, 0))
OVER(PARTITION BY main_clld.Distributor, main_clld.Network,
main_clld.Product, EOMONTH(main_clld.DocumentDate))
我认为您的完整查询最终会是:
SELECT
Distributor,
Network,
Product,
MonthYear,
SUM(Weight) AS MonthlyWeight,
IsPromo
FROM (SELECT
main_clld.Distributor,
main_clld.Network,
main_clld.Product,
main_clld.DocumentDate,
main_clld.Weight,
main_clld.Quantity,
main_clld.AmountCP,
CAST(MONTH(DocumentDate) AS VARCHAR(2)) + '.' + cast(year(DocumentDate) as VARCHAR(2)) AS MonthYear,
CASE WHEN (main_clld.AmountCP / main_clld.Quantity) < MAX(main_clld.AmountCP / NULLIF(main_clld.Quantity, 0))
OVER(PARTITION BY main_clld.Distributor, main_clld.Network,
main_clld.Product, EOMONTH(main_clld.DocumentDate))
THEN 1 ELSE 0 END AS IsPromo
FROM CisLinkLoadedData AS main_clld
WHERE main_clld.Quantity > 0
AND main_clld.GCRecord IS NULL
) AS bad_query
GROUP BY
Distributor,
Network,
Product,
MonthYear,
IsPromo;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.