我在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的此任务。
答案 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