[英]Rolling 12/24 Month Average Price
我一直停留在這個邏輯上,最后向社區尋求幫助。 我正在制作使用以下邏輯的價格差異圖表:
Total Volume Previous Year - 如果該商品在過去 12 個月的交易量是 NULL,這意味着該商品從未售出,則 0 ELSE
(過去 12 個月內該項目所有交易的平均價格 - 該項目過去 13-24 個月內所有交易的平均價格) X(當年總交易量)
我嘗試使用 WITH 高級 SQL 查詢來打破過去 12 個月和當前日期前 13-24 個月的平均價格,但我認為我的 WHERE 語句沒有這樣做:
SELECT
inv_item_mst.item,
AVG(inv_item_mst.price*(1-(inv_item_mst.disc/100))) AS [AvgPreviousPrice],
SUM(inv_item_mst.qty_invoiced) AS [PreviousVolume],
inv_hdr_mst.cust_num
FROM inv_item_mst
LEFT JOIN inv_hdr_mst
ON inv_item_mst.inv_num=inv_hdr_mst.inv_num
WHERE YEAR(inv_hdr_mst.inv_date) = YEAR(DATEADD(YEAR,-1,GETDATE()))
GROUP BY inv_item_mst.item,
inv_hdr_mst.cust_num
我使用 WHERE YEAR(inv_hdr_mst.inv_date) = YEAR(DATEADD(YEAR,0,GETDATE())) 復制了相同的代碼,以獲取當前交易量和當前平均價格。
關於我可以更改 WHERE 以跟蹤 0-11 個月(當前)和 12-23 個月(以前)范圍內的所有交易的平均價格和交易量的任何想法?
注意:我還需要添加邏輯,說明該項目是否在前 12 個月內不存在,而不是我需要它為 0。我將這兩個查詢與一個主項目表連接起來,以確保我得到他們正在嘗試的所有項目不分年份進行跟蹤。
因為您沒有指定您想要的 output 格式,所以您的問題有多種解決方案。
此外,您的問題包含一些關於如何計算“滾動”平均值的相互矛盾的信息。 與使用實際年份值相比,[0-11] 和 [12,13] 個月等日期范圍會產生不同的結果。 下面的例子證明了我的觀點。
today = 2020-07-22
current 12 months = [2019-07-22, 2020-07-22] --> defined with dateadd(year, -1, ...)
current year = 2020 --> defined with year(...)-1
previous 12 months = [2018-07-22, 2019-07-21] --> defined with dateadd(year, -2, ...)
previous year = 2019 --> defined with year(...)-2
樣本數據
定義表結構
declare @item table
(
ItemId int,
ItemName nvarchar(20)
);
declare @trans table
(
ItemId nvarchar(20),
TransDate date,
TransVolume int,
TransPrice money
);
確定樣本數據的日期范圍
select convert(date,getdate()) as 'today',
dateadd(year, -1, convert(date,getdate())) as 'start last year',
dateadd(year, -2, convert(date,getdate())) as 'start last 2 years';
today start last year start last 2 years
---------- --------------- ------------------
2020-07-22 2019-07-22 2018-07-22
插入一些示例數據
insert into @item (ItemId, ItemName) values
(1, 'Awesome product'),
(2, 'Mega item'),
(3, 'Super stuff'),
(4, 'Weird thing'); -- will not be sold
insert into @trans (ItemId, TransDate, TransVolume, TransPrice) values
(1, '2017-01-01', 99, 9.99), -- before last 2 years, to be excluded
(1, '2019-01-01', 10, 1.20), -- in last 2 years
(1, '2019-05-01', 7, 1.50), -- in last 2 years
(1, '2019-06-01', 1, 1.00), -- in last 2 years
(1, '2020-03-01', 8, 2.00), -- in last 1 year
(2, '2019-03-01', 12, 0.75), -- in last 2 years
(2, '2019-08-01', 3, 1.20), -- in last 1 year
(2, '2019-10-01', 10, 1.20), -- in last 1 year
(2, '2020-07-01', 9, 0.80), -- in last 1 year
(3, '2019-04-01', 7, 1.20), -- in last 2 years
(3, '2019-05-01', 11, 1.50), -- in last 2 years
(3, '2020-04-01', 3, 0.80), -- in last 1 year
(3, '2020-05-01', 2, 1.25); -- in last 1 year
解決方案 1
此解決方案並排(在同一行)顯示各個周期的值。 這兩個時段有兩個外部應用子查詢。 當前和上一個期間是使用日期范圍計算的。
select i.ItemName,
isnull(calc1.SumVol, 0) as 'SumVolume1', -- volume in last 2 years
isnull(calc1.AvgPri, 0) as 'AvgPrice1', -- average price in last 2 years
isnull(calc2.SumVol, 0) as 'Volume2', -- volume in last 1 year
isnull(calc2.AvgPri, 0) as 'AvgPrice2' -- average price in last 1 year
from @item i
outer apply ( select sum(t2.TransVolume) as 'SumVol',
avg(t2.TransPrice) as 'AvgPri'
from @trans t2
where t2.ItemId = i.ItemId
and t2.TransDate >= dateadd(year, -2, convert(date,getdate()))
and t2.TransDate < dateadd(year, -1, convert(date,getdate())) ) calc1
outer apply ( select sum(t1.TransVolume) as 'SumVol',
avg(t1.TransPrice) as 'AvgPri'
from @trans t1
where t1.ItemId = i.ItemId
and t1.TransDate >= dateadd(year, -1, convert(date,getdate())) ) calc2;
結果如下所示:
ItemName SumVolume1 AvgPrice1 Volume2 AvgPrice2
-------------------- ----------- --------------------- ----------- ---------------------
Awesome product 18 1,2333 8 2,00
Mega item 12 0,75 22 1,0666
Super stuff 18 1,35 5 1,025
Weird thing 0 0,00 0 0,00
解決方案 2
此解決方案在彼此下方(不同的行)顯示不同時期的值。 它使用使用with
關鍵字定義的公用表表達式(CTE)。 對於沒有事務的項目,您會得到一行null
(可以用isnull()
替換)。 當前和上一期間再次使用日期范圍計算。
with cte_TransRange as
(
select case
when t.TransDate >= dateadd(year, -1, convert(date,getdate())) then -1
when t.TransDate >= dateadd(year, -2, convert(date,getdate())) then -2
else 0
end as 'YearRange',
t.ItemId,
t.TransPrice,
t.TransVolume
from @trans t
)
select i.ItemName,
tr.YearRange,
isnull(sum(tr.TransVolume),0) as 'SumVolume',
isnull(avg(tr.TransPrice),0) as 'AvgPrice'
from @item i
left join cte_TransRange tr
on tr.ItemId = i.ItemId
and tr.YearRange <> 0
group by i.ItemName,
tr.YearRange
order by i.ItemName;
這以另一種格式給出相同的數字:
ItemName YearRange SumVolume AvgPrice
-------------------- ----------- ----------- ---------------------
Awesome product -2 18 1,2333
Awesome product -1 8 2,00
Mega item -2 12 0,75
Mega item -1 22 1,0666
Super stuff -2 18 1,35
Super stuff -1 5 1,025
Weird thing NULL 0 0,00
解決方案 3
解決方案 2 的變體,但我現在使用的是實際年份,而不是使用日期范圍。 因此,這個版本要短得多(也更簡單)。
select i.ItemName,
year(t.TransDate) as 'Year',
isnull(sum(t.TransVolume),0) as 'SumVolume',
isnull(avg(t.TransPrice),0) as 'AvgPrice'
from @item i
left join @trans t
on t.ItemId = i.ItemId
and year(t.TransDate) > year(getdate())-2
group by i.ItemName,
year(t.TransDate)
order by i.ItemName;
但是與之前的數字相比,這會產生不同的結果!
ItemName Year SumVolume AvgPrice
-------------------- ----------- ----------- ---------------------
Awesome product 2019 18 1,2333
Awesome product 2020 8 2,00
Mega item 2019 25 1,05
Mega item 2020 9 0,80
Super stuff 2019 18 1,35
Super stuff 2020 5 1,025
Weird thing NULL 0 0,00
希望這能解決你的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.