2013-11-09 1 views
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 

ответ

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 
+0

Спасибо. Я не уверен, что вы имеете в виду: «если у вас есть предельное значение, например, 00:30:00, его следует рассматривать только один раз». Это еще не достигнуто: a.StartRange <метка времени и a.EndRange> = отметка времени? – cs0815

+0

Вы правы :) –

+0

Я еще не тестировал ваш подход, но мой довольно медленный, как только я пытаюсь сделать это в течение месяца или более. Считаете ли вы, что ваш подход быстрее? – cs0815

Смежные вопросы