我需要你的帮助。
数据库:SQL SERVER 2008R2
我想计算一周和一周的最后4周的平均价值。
我的数据表是这样的:
YEAR WEEKS VALUE
2012 1 3000
2012 2 5000
2012 3 6000
2012 4 7000
2012 5 8000
2012 6 9000
2012 7 1000
2012 8 6000
2012 9 9000
2012 10 4000
我想要那个:
YEAR WEEKS VALUE
2012 1 ( Average value for week 49, 50, 51, 52 for the year 2011)
2012 2 ( Average value for week 50, 51, 52 for the year 2011 and week 1 for the year 2012)
2012 3 ( Average value for week 51, 52 for the year 2011 and week 1, 2 for the year 2012)
2012 4 ( Average value for week 52 for the year 2011 and week 1, 2, 3 for the year 2012)
2012 5 5250 -> ( Average value for week 1, 2, 3 , 4 for the year 2012)
2012 6 6500 -> ( Average value for week 2, 3 , 4, 5 for the year 2012)
答案 0 :(得分:3)
如果岁月总是有52周,那么这里有一个简单的方法:
SELECT
DataYear = N.Serial / 52,
DataWeek = N.Serial % 52 + 1,
Avg(T.Value)
FROM
dbo.DataTable T
CROSS JOIN (VALUES (0), (1), (2), (3)) W (Offset)
CROSS APPLY (SELECT T.Year * 52 + Week + W.Offset) N (Serial)
GROUP BY
N.Serial / 52,
N.Serial % 52 + 1
HAVING
Count(*) = 4 -- if you don't want smaller sets
ORDER BY
DataYear,
DataWeek;
See this in action in a SQLFiddle。我不得不在2011年底添加假数据以匹配您的示例输出。我从Alexander Fedorenko那里借用了2011年的数据,以便进行比较。
注意:如果年份的周数可变,则不会那么简单。为了获得更好的答案,您需要提供有关如何计算周数的详细说明,足够的详细信息,以便我们确定一年中每周的实际开始日期。
最终,将数据分成数年和数周存储可能不是最佳的。我认为最好只存储每周收集数据的周开始日期。
答案 1 :(得分:1)
使用递归CTE
;WITH cte AS
(
SELECT [YEAR], WEEKS, VALUE,
ROW_NUMBER() OVER (ORDER BY [YEAR], WEEKS) AS id
FROM your_table
--WHERE your condition range of dates
), cte2 AS
(
SELECT id,
CASE WHEN id = 5 THEN [YEAR] END AS [YEAR],
CASE WHEN id = 5 THEN WEEKS END AS WEEKS,
CASE WHEN id != 5 THEN VALUE END AS VALUE, 1 AS [Level]
FROM cte
UNION ALL
SELECT c.id,
CASE WHEN ct.id - ct.[Level] = 4 THEN c.[YEAR] END,
CASE WHEN ct.id - ct.[Level] = 4 THEN c.WEEKS END,
CASE WHEN ct.id - ct.[Level] != 4 THEN c.VALUE END, ct.[Level] + 1
FROM cte c JOIN cte2 ct ON c.id = ct.id + 1
WHERE ct.id < 5 + [Level]
)
SELECT MAX([YEAR]) AS [YEAR], MAX(WEEKS) AS WEEKS, AVG(VALUE) AS avgVALUE
FROM cte2
WHERE id = CASE WHEN [Level] = 1 AND id > 5 THEN NULL ELSE id END
GROUP BY [level]
HAVING MAX([YEAR]) IS NOT NULL
SQLFiddle上的演示
答案 2 :(得分:0)
首先,不要在多个字段之间分割日期信息,这意味着必须重新组合以减慢查询速度,最好将其存储为日期时间变量。
其次,答案是
WITH Data
AS
(
SELECT CAST(CAST(Year AS VARCHAR) + CAST(Weeks AS VARCHAR) AS INTEGER) AS WeekNum
,Year
,Weeks
,Value
,1 AS Depth
FROM WeekData
UNION ALL
SELECT d.WeekNum
,d.Year
,d.Weeks
,wd.Value
,d.Depth + 1
FROM WeekData wd
INNER JOIN
Data d ON d.WeekNum=CAST(CAST(wd.Year AS VARCHAR) + CAST(wd.Weeks AS VARCHAR) AS INTEGER)-d.Depth
AND
d.Depth<4
)
SELECT Year
,Weeks
,AVG(Value) AS AverageValue
FROM Data
GROUP BY Year
,Weeks