任何人都知道编写查询以将当前月份的收入与过去6个月的平均月收入进行比较的有效方法吗?
以下是仅有2列的示例,实际月份和月份收入
列:
MonthYear RevenueAmt
Jan2017 120
Dec2016 75
Nov2016 50
Oct2016 100
Sep2016 75
Aug2016 100
Jul2016 100
所以....前6个月(7月到12月)的平均值是
(75 + 50 + 100 + 75 + 100 + 100) = 500
500 / 6 = 83.33
本月(2017年1月)是120, 所以区别变成了 -
120 - 83.33 = 36.67
因此,2017年1月比过去6个月的平均值高36.67。
答案 0 :(得分:2)
您可以使用窗口功能并通过ROWS BETWEEN 6 PRECEDING AND 1 PRECEDING
这是滚动变化,我确实进行了一次修改 ...我使用了实际日期,因此我们可以在Order By
子句中设置正确的Over
< / p>
编辑:我添加了Prior6MthAvg列来说明数学
Declare @YourTable table (MonthYear Date,RevenueAmt int)
Insert Into @YourTable values
('2017-01-01',120),
('2016-12-01',75),
('2016-11-01',50),
('2016-10-01',100),
('2016-09-01',75),
('2016-08-01',100),
('2016-07-01',100)
Select A.*
,Prior6MthAvg = avg(RevenueAmt+0.0) over (Order By MonthYear ROWS BETWEEN 6 PRECEDING AND 1 PRECEDING)
,Variance = RevenueAmt-avg(RevenueAmt+0.0) over (Order By MonthYear ROWS BETWEEN 6 PRECEDING AND 1 PRECEDING)
From @YourTable A
Order by MonthYear Desc
返回
MonthYear RevenueAmt Prior6MthAvg Variance
2017-01-01 120 83.333333 36.666667
2016-12-01 75 85.000000 -10.000000
2016-11-01 50 93.750000 -43.750000
2016-10-01 100 91.666666 8.333334
2016-09-01 75 100.000000 -25.000000
2016-08-01 100 100.000000 0.000000
2016-07-01 100 NULL NULL
答案 1 :(得分:-1)
我要发表评论,但这更像是一个答案....
请注意:效率和规划需要更广泛的设计范围。
总的来说 - 假设数据量较大 - 最佳方式(根据我的经验)是为表格保留一个单独的表格。 &#34;运行平均值。&#34;
为了解释,我会保留一个单独的表(单个记录,如果只有一组数据 - 即不是基于公司的),按当前月份键入,给定平均值和第6个月总数。
完成后 - 插入一个触发器,用于添加新月(一般情况下,或通过公司,如果分开),将扣除第6个月,并添加当前。
然后,将总数,平均数或两者分开存储,并快速访问。
完成后 - 一个简单的连接会将总数/平均数带入任何给定的查询。
编辑添加:(注意:我的T-SQL可能生锈,但这应该给你的想法) 注意:它假定ClientData的基表,具有辅助表SalesAvg,由id(代表)和日期(月份标记)链接,如果日期可以变化,则需要拆分密钥的月/年和链接)。尽管投票率很低,但我还是指出了原来的评论。从给定的表中拉出它将基本上在查询点对服务器进行任务。此方法将工作分配到插入点(通常更加分散),并且当平均值被键控时,允许使用内部连接进行最快速的检索。
CREATE TRIGGER UpdateSalesAvg
ON schema.ClientData
AFTER INSERT
AS
DECLARE @ID as INT;
DECLARE @Date as DATE;
DECLARE @Count as INT;
SET @ID=new.id;
SET @Date=new.date;
SELECT @Count = ISNULL(RunCount, 0) FROM schema.SalesAvg
WHERE id = @ID AND monthdate = @Date;
IF (@Count = 0)
BEGIN
INSERT INTO schema.SalesAvg (id, monthdate, RunAvg, RunCount, LastPost)
VALUES (new.id, new.monthdate, new.value, 1, new.value);
END
ELSE IF (@Count = 6)
BEGIN
UPDATE schema.SalesAvg
SET RunAvg = ROUND((RunAvg * 6) - LastPost + new.value) / 6, 2),
LastPost = new.value
WHERE id = @ID
AND monthdate = @Date;
END
ELSE
BEGIN
UPDATE schema.SalesAvg
SET RunAvg = ROUND( (RunAvg * RunCount + new.value) / (RunCount + 1), 2 ),
RunCount = RunCount + 1,
LastPost = new.value
WHERE id = @ID
AND monthdate= @Date;
END
GO
希望能够解释它。 - 约翰