实现3天均线

时间:2016-08-24 05:47:34

标签: sql sql-server sql-server-2008 sql-server-2012

我在SQL Server中遇到任务有问题。表的名称是'test'。

CREATE TABLE test 
(
    [entry_date] [date] NOT NULL,
    [value] [int] NOT NULL,
    [id] [int] NULL,
)

INSERT test VALUES ( '2012-02-01', 10, 1);
INSERT test VALUES ( '2012-02-02', 20, 2);
INSERT test VALUES ( '2012-02-03', 10, 1);
INSERT test VALUES ( '2012-02-04', 30, 2);
INSERT test VALUES ( '2012-02-05', 10, 1);
INSERT test VALUES ( '2012-02-06', 11, 3);
INSERT test VALUES ( '2012-02-06', 40, 1);
INSERT test VALUES ( '2012-02-07', 10, 2);
INSERT test VALUES ( '2012-02-08', 50, 3);
INSERT test VALUES ( '2012-02-09', 10, 2);
INSERT test VALUES ( '2012-02-10', 60, 2);
INSERT test VALUES ( '2012-02-10', 50, 4);
INSERT test VALUES ( '2012-02-11', 51, 3);

根据以上数据,我想获得如下输出:

   entry_date |value |id |averagevaluesof_3days
-----------+------+---+----------------------
2012-02-01 |10    |1  | 0       -----here we donot have last3rdaysdate
2012-02-03 |10    |1  | 6.6-------last 3days feb3 and feb2 and feb1
2012-02-05 |10    |1  | 6.6
2012-02-06 |40    |1  | 0 ----here we donot have last3rdaysdate(4th date is missed)
2012-02-02 |20    |2  | 0
2012-02-04 |30    |2  | 16.6
2012-02-07 |10    |2  | 0
2012-02-09 |10    |2  | 6.6
2012-02-10 |60    |2  | 0
2012-02-06 |11    |3  | 0
2012-02-08 |50    |3  | 20.3
2012-02-11 |51    |3  | 0
2012-02-10 |50    |4  | 0

我需要根据id计算日期(entry_date)最近三天信息运行的平均值。

如果entry_date在日期(entry_date)没有最后第3天的信息,则认为日期平均为0.

让我举一个例子进一步解释我的目标:

 here we need to consider based on id wise
 if we consider id=1 related information

- If the `Entry_date: 2012-02-01`, this date have value and back 2 days don't have value less than 2012-02-01 average value is 0 

- If the `Entry_date: 2012-02-03`, this date have value and back 2 days means 2012-02-01 and 2012-01-02. Here we can take 3 days average for 2012-02-03 date is 6.6 ((10+0+10)/3 =6.6) if we take 2012-02-05 is 6.6 ((10+0+10)/3 = 6.6)
- If the `Entry_date: 2012-02-01`, this date have value and back 2 days don't have value less than 2012-02-01 average value is 0 

if we consider id=2 related information
- If the `Entry_date: 2012-02-02`, this date have value and back 2 days means 2012-02-01 and 2012-01-31,don't have value then average value is 0
- If the `Entry_date: 2012-02-04`, this date have value and back 2 days means 2012-02-03 and 2012-02-02. Here we can take 3 days average for 2012-02-04 date is 16.6 ((30+0+20)/3 =16.6) if we take 2012-02-07 is 0 because of last 3rd date dont have

- If the `Entry_date: 2012-02-09`, this date have value and back 2 days means 2012-02-08 and 2012-02-07. Here we can take 3 days average for 2012-02-09 date is 6.6 ((10+0+10)/3 =6.6) if we take 2012-02-10 is 0 because of last 3rd date dont have

请告诉我如何编写查询以实现SQL Server的此任务。

2 个答案:

答案 0 :(得分:1)

试试这个,

   SELECT x.entry_date
    ,x.value
    ,x.id
    ,convert(DECIMAL(18, 2), CASE 
            WHEN (
                    SELECT count(*)
                    FROM test
                    WHERE id = x.id
                        AND entry_date <= (x.entry_date)
                    ) >= 3
                THEN avg(value) OVER (
                        PARTITION BY id ORDER BY id
                            ,entry_date rows BETWEEN 2 preceding
                                AND CURRENT row
                        )
            ELSE 0
            END) AS rollingavg
FROM (
    SELECT id
        ,entry_date
        ,convert(DECIMAL(18, 2), sum(value)) AS value
    FROM test
    GROUP BY id
        ,entry_date
    ) x

答案 1 :(得分:0)

试试这个

    CREATE table #test
(
    [entry_date] [date] NOT NULL,
    [value] [int] NOT NULL,
    [id] [int] NULL
)

INSERT #test VALUES ( '2012-02-01', 10, 1);
INSERT #test VALUES ( '2012-02-02', 20, 2);
INSERT #test VALUES ( '2012-02-03', 10, 1);
INSERT #test VALUES ( '2012-02-04', 30, 2);
INSERT #test VALUES ( '2012-02-05', 10, 1);
INSERT #test VALUES ( '2012-02-06', 11, 3);
INSERT #test VALUES ( '2012-02-06', 40, 1);
INSERT #test VALUES ( '2012-02-07', 10, 2);
INSERT #test VALUES ( '2012-02-08', 50, 3);
INSERT #test VALUES ( '2012-02-09', 10, 2);
INSERT #test VALUES ( '2012-02-10', 60, 2);
INSERT #test VALUES ( '2012-02-10', 50, 4);
INSERT #test VALUES ( '2012-02-11', 51, 3);

SELECT              
    CurrentRow.entry_date,
    CurrentRow.value,
    CurrentRow.id,
    CASE 
        WHEN ISNULL(PriviousRow1.value, 0) = 0 OR
             ISNULL(PriviousRow2.value, 0) = 0 THEN 0.00
        ELSE 
            (ISNULL(CurrentRow.value, 0) +
             ISNULL(PriviousRow1.value, 0) +
             ISNULL(PriviousRow2.value, 0)) / 3.0 END averagevaluesof_3days

FROM
    #test CurrentRow LEFT JOIN 
    #test PriviousRow1 ON CONVERT(VARCHAR(8), DATEADD(DAY, -1, CurrentRow.entry_date), 112) = 
                          CONVERT(VARCHAR(8), PriviousRow1.entry_date, 112) LEFT JOIN 
    #test PriviousRow2 ON CONVERT(VARCHAR(8), DATEADD(DAY, -2, CurrentRow.entry_date), 112) = 
                          CONVERT(VARCHAR(8), PriviousRow2.entry_date, 112)
ORDER BY 
    CurrentRow.entry_date

结果:

entry_date      value       id          averagevaluesof_3days
----------      ----------- ----------- ---------------------------------------
2012-02-01      10          1           0.00
2012-02-02      20          2           0.00
2012-02-03      10          1           13.33
2012-02-04      30          2           20.00
2012-02-05      10          1           16.66
2012-02-06      11          3           17.00
2012-02-06      40          1           26.66
2012-02-07      10          2           10.33
2012-02-07      10          2           20.00
2012-02-08      50          3           23.66
2012-02-08      50          3           33.33
2012-02-09      10          2           23.33
2012-02-10      60          2           40.00
2012-02-10      50          4           36.66
2012-02-11      51          3           40.33
2012-02-11      51          3           37.00