我试图获得一些稀疏原始数据的平均间隔值,用于每个定义的开始和结束日期/时间加上间隔大小(以秒为单位)。这是我的第一次尝试:
declare
@StartTime datetime = '2013-11-01 00:00:00.000',
@EndTime datetime = '2013-11-02 00:00:00.000',
@IntervalInSeconds int = 1800
drop table #Events
create table #Events
(
Timestamp datetime,
DisplayValue real
)
insert into #Events (Timestamp, DisplayValue) values ('2013-11-01 00:00:01.000', 2)
insert into #Events (Timestamp, DisplayValue) values ('2013-11-01 00:00:01.000', 3)
insert into #Events (Timestamp, DisplayValue) values ('2013-11-01 00:30:01.000', 4)
insert into #Events (Timestamp, DisplayValue) values ('2013-11-01 00:30:01.000', 5)
;WITH CompleteSequence AS
(
SELECT
@StartTime AS StartRange,
DATEADD(second, @IntervalInSeconds, @StartTime) AS EndRange
UNION ALL
SELECT
EndRange,
DATEADD(second, @IntervalInSeconds, EndRange)
FROM CompleteSequence
WHERE DATEADD(second, @IntervalInSeconds, EndRange) <= @EndTime
)
SELECT
StartRange,
AVG(NULLIF(DisplayValue,0))
FROM CompleteSequence as a
left outer join #Events as b on a.StartRange < Timestamp and a.EndRange >= Timestamp
where Timestamp >= @StartTime and Timestamp <= @EndTime
group by StartRange
不幸的是,结果:
2013-11-01 00:00:00.000 2.5
2013-11-01 00:30:00.000 4.5
应该是48个值,其中“缺失数据”理想地应该用整个时间段内的平均值估算(在这种情况下(2 + 3 + 4 + 5)/ 4 = 3.5。我使用NULLIF等。至少0没有成功。任何想法?
PS:
这是另一种尝试,似乎有效。任何改进建议都欢迎:
declare
@StartTime datetime = '2013-11-01 00:00:00.000',
@EndTime datetime = '2013-11-02 00:00:00.000',
@IntervalInSeconds int = 1800,
@Average real = 0
drop table #Events
create table #Events
(
Timestamp datetime,
DisplayValue real
)
insert into #Events (Timestamp, DisplayValue) values ('2013-11-01 00:00:01.000', 2)
insert into #Events (Timestamp, DisplayValue) values ('2013-11-01 00:00:01.000', 3)
insert into #Events (Timestamp, DisplayValue) values ('2013-11-01 00:30:01.000', 4)
insert into #Events (Timestamp, DisplayValue) values ('2013-11-01 00:30:01.000', 5)
select @Average = AVG(DisplayValue) from #Events
;WITH CompleteSequence AS
(
SELECT
@StartTime AS StartRange,
DATEADD(second, @IntervalInSeconds, @StartTime) AS EndRange
UNION ALL
SELECT
EndRange,
DATEADD(second, @IntervalInSeconds, EndRange)
FROM CompleteSequence
WHERE DATEADD(second, @IntervalInSeconds, EndRange) <= @EndTime
)
SELECT
StartRange,
ISNULL(AVG(DisplayValue), @Average)
FROM CompleteSequence as a
left outer join #Events as b on (a.StartRange < Timestamp and a.EndRange >= Timestamp)
where (Timestamp >= @StartTime and Timestamp <= @EndTime) or Timestamp is null
group by StartRange
答案 0 :(得分:1)
我可能得到了类似的结果。您应该知道,如果您有一个限制值,例如00:30:00
,则只应考虑一次。
DECLARE @IntervalInSeconds int = 1800 ,
@StartTime datetime = '2013-11-01 00:00:00.000',
@EndTime datetime = '2013-11-02 00:00:00.000'
;WITH SampleData AS
(
SELECT [Timestamp], [DisplayValue]
FROM ( VALUES
('2013-11-01 00:00:01.000', 2.0),
('2013-11-01 00:00:01.000', 3.0),
('2013-11-01 00:30:01.000', 4.0),
('2013-11-01 00:30:01.000', 5.0)
) AS SampleData([Timestamp], [DisplayValue])
), WorkSet AS
(
SELECT CAST(CAST(MIN([Timestamp]) AS DATE) AS DATETIME) StartDate, -- OR @StartTime
DATEADD(day, +1, CAST(MAX([Timestamp]) AS DATE)) EndDate, -- OR @EndTime
AVG ([DisplayValue]) AverageValue
FROM SampleData
), Sequence AS
(
SELECT 1 as [Order],
WorkSet.StartDate StartRange,
DATEADD(second, @IntervalInSeconds, WorkSet.StartDate) EndRange,
WorkSet.EndDate Limit
FROM WorkSet
UNION ALL
SELECT [Order] + 1,
EndRange,
DATEADD(second, @IntervalInSeconds, EndRange),
Sequence.Limit
FROM Sequence
WHERE EndRange < Sequence.Limit
), ResultSet AS
(
SELECT Sequence.[Order],
Sequence.[StartRange],
Sequence.[EndRange],
AVG(ISNULL(SampleData.DisplayValue, WorkSet.AverageValue)) Value
FROM WorkSet, Sequence
LEFT JOIN SampleData
ON SampleData.[Timestamp] >= Sequence.[StartRange] AND
SampleData.[Timestamp] < Sequence.[EndRange]
GROUP BY Sequence.[Order],
Sequence.[StartRange],
Sequence.[EndRange]
)
SELECT *
FROM ResultSet