在同一天的6周移动平均值

时间:2017-08-30 14:02:45

标签: sql-server sql-server-2014 rows between moving-average

我正在计算一周中同一天的6周移动平均值,用于呼叫中心的呼叫量。

我的意思是前6天(过去6个星期二,过去6个星期三等)。

我已经使用了以下代码,但根本没有灵活性:

SELECT
    [ROW_DATE],
    [DEPARTMENT_DESC],
    [totalcalls],
    AVG([TOTALCALLS]) OVER(ORDER BY [DEPARTMENT_DESC],
                                    [ROW_DATE] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS [MOVING_AVG]
FROM
(
    SELECT
        [ROW_DATE] AS [ROW_DATE],
        [DEPARTMENT_DESC] AS [DEPARTMENT_DESC],
        SUM([CALLS_OFFERED_ACTUALS]) AS [TOTALCALLS]
    FROM [GEMDB].[dbo].[V_PRD_ACT_HSPLIT_intradayLCWcallsTable]
    WHERE ROW_DATE IN(CONVERT(DATE, GETDATE() - 42), CONVERT(DATE, GETDATE() - 7), CONVERT(DATE, GETDATE() - 14), CONVERT(DATE, GETDATE() - 21), CONVERT(DATE, GETDATE() - 28), CONVERT(DATE, GETDATE() - 35))
    AND [DEPARTMENT_DESC] = 'techops'
    GROUP BY
        ROW_DATE,
        [DEPARTMENT_DESC]
) AS tbl
ORDER BY
    ROW_DATE,
    [DEPARTMENT_DESC];

输出如下: Moving Average for August 23rd

上述代码的问题是它给出了一周中1天(8月23日)的价值。 我想获得过去7天的6周移动平均线,而不是写GETDATE 49次,这将是疯狂的。

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:0)

如果我理解正确的话,我已经尝试创建一个简单的例子。这使用了2周的数据,但应该适用于较大的数据集。如果符合您的要求,您可以单独运行此代码以进行测试和调整:

CREATE TABLE #calls
(
    TotalCalls INT,
    CallDate DATE
);

-- 2 weeks worth of calls
INSERT INTO #calls
(
    TotalCalls,
    CallDate
)
VALUES
(12, '20170801'), -- starts on a Tuesday
(13, '20170802'),
(17, '20170803'),
(20, '20170804'),
(4, '20170805'),
(8, '20170806'),
(10, '20170807'),
(14, '20170808'),
(18, '20170809'),
(16, '20170810'),
(7, '20170811'),
(11, '20170812'),
(19, '20170813'),
(14, '20170814');

-- casts to numeric with decimal places for the average for accuracy
-- DayName - gives the day names for grouping
-- DayNo - gives you the day number for ordering
-- Instances - gives you how many days were included in the average
-- WHERE - filters to dates >= date - 42 for 6 weeks
SELECT AVG(CAST(c.TotalCalls AS NUMERIC(5,2))) AvgCalls,
       DATENAME(dw,c.CallDate ) DayName,
       DATEPART(dw, c.CallDate) DayNo,
       COUNT(c.CallDate) Instances
FROM #calls AS c
WHERE c.CallDate > GETDATE() - 42
GROUP BY DATENAME(dw, c.CallDate ), DATEPART(dw, c.CallDate)
ORDER BY DATEPART(dw, c.CallDate)

<强>产地:

AvgCalls    DayName    DayNo    Instances
13.500000   Sunday     1        2
12.000000   Monday     2        2
13.000000   Tuesday    3        2
15.500000   Wednesday  4        2
16.500000   Thursday   5        2
13.500000   Friday     6        2
7.500000    Saturday   7        2

答案 1 :(得分:0)

这是另一种选择......

WITH
    cte_SixWeekCal AS (
        SELECT 
            c.WEEK_NO,
            ROW_DATE_BEG = DATEADD(WEEK, -13 + c.WEEK_NO, CAST(GETDATE() AS DATE)),
            ROW_DATE_END = DATEADD(WEEK, -7 + c.WEEK_NO, CAST(GETDATE() AS DATE))
        FROM 
            ( VALUES (1), (2), (3), (4), (5), (6) ) c (WEEK_NO)
        )
SELECT 
    swc.WEEK_NO,
    ROW_DATE = ROW_DATE_END,
    ahid.DEPARTMENT_DESC.
    ahid.MOVING_AVG
FROM 
    cte_SixWeekCal swc
    CROSS APPLY (
                SELECT 
                    ahi.DEPARTMENT_DESC,
                    MOVING_AVG = AVG(ahi.CALLS_OFFERED_ACTUALS)
                FROM 
                    [GEMDB].dbo.V_PRD_ACT_HSPLIT_intradayLCWcallsTable ahi
                WHERE 
                    ih.InvoiceDate >= swc.ROW_DATE_BEG
                    AND ih.InvoiceDate <= swc.ROW_DATE_END
                GROUP BY
                    ahi.DEPARTMENT_DESC
                ) ahid;