本月与过去6个月的平均值相比

时间:2017-03-27 16:58:55

标签: sql-server

任何人都知道编写查询以将当前月份的收入与过去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。

2 个答案:

答案 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  

希望能够解释它。 - 约翰