[英]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.