0

我正在尝试为每个定义的开始和结束日期/时间加上间隔大小(以秒为单位)获取一些稀疏原始数据的平均间隔值。这是我的第一个刺:

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
4

1 回答 1

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
于 2013-11-09T11:35:13.803 回答