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 に答える