Цикл скользящего среднего в SQL - PullRequest
0 голосов
/ 19 мая 2018

Я пытаюсь сделать функцию сглаживания с помощью циклического скользящего среднего в SQL.Мой текущий код для нецикличного метода выглядит следующим образом:

CREATE TABLE #Input ( 
         PartitionID  int
       , TimeID     int
       , Quantity float );

INSERT INTO #Input
  VALUES
   ( 1, 1, 2 ),
   ( 1, 2, 4 ),
   ( 1, 3, 6 ),
   ( 1, 4, 16 ),
   ( 2, 4, 6 ),
   ( 2, 5, 1 ),
   ( 2, 6, 9 ),
   ( 2, 7, 2 );

SELECT *
  FROM #Input;

-- Actual code
UPDATE i
  SET i.Quantity = i2.c
  FROM #Input i
       JOIN ( SELECT PartitionID AS a
                   , TimeID AS b
                   , AVG(Quantity) OVER(Partition BY PartitionID ORDER BY TimeID ASC ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS c
                FROM #Input
            ) i2
               ON i2.a = i.PartitionID
                  AND i2.b = i.TimeID;
-- /Actual code

SELECT *
  FROM #Input;

Я хотел бы сделать этот цикл, чтобы первая строка каждого раздела ссылалась на последнюю строку и наоборот.Есть мысли?

РЕДАКТИРОВАТЬ: Желаемый результат будет:

1    1    7.33
1    2    4
1    3    8.66
1    4    8
2    4    3
2    5    5.33
2    6    4
2    7    5.66

1 Ответ

0 голосов
/ 24 мая 2018

Это действительно очень интересный вопрос.Я пытаюсь расширить исходную таблицу, добавив две строки для каждой группы PartitionID, одну с максимальным (TimeID) +1, а другую с min (TimeID) -1, в то время как значение [Количество] является противоположным.Например, для PartitionID = 1 я добавлю две строки, чтобы исходные четыре строки были разделены на шесть строк следующим образом (добавлены первая и последняя две строки)

( 1, 0, 16 )  
( 1, 1, 2 ),
( 1, 2, 4 ),
( 1, 3, 6 ),
( 1, 4, 16 ),
( 1, 5, 2 )

Весь запрос выглядит следующим образом:

--drop table #input;
CREATE TABLE #Input ( 
         PartitionID  int
       , TimeID     int
       , Quantity float );

INSERT INTO #Input
  VALUES[![enter image description here][1]][1]
   ( 1, 1, 2 ),
   ( 1, 2, 4 ),
   ( 1, 3, 6 ),
   ( 1, 4, 16 ),
   ( 2, 4, 6 ),
   ( 2, 5, 1 ),
   ( 2, 6, 9 ),
   ( 2, 7, 2 );

select * from #Input;

   ; with c as (
                select partitionid, min_timeid = min(timeid), max_timeid = max(timeid)
                from #Input
                group by partitionid
               )
, c2 as (
            select c.PartitionID, TimeID= c.max_timeid+c.min_timeid-i.TimeID + case i.TimeID when c.max_timeid then -1 else 1 end , i.Quantity
            from c
            inner join #input i
            on c.partitionid = i.PartitionID
            and i.TimeID in (c.max_timeid, c.min_timeid)
            union
            select * from #Input
)
update i 
set i.Quantity = i2.c
from #Input i
inner join ( SELECT PartitionID AS a
                   , TimeID AS b
                   , AVG(Quantity) OVER(Partition BY PartitionID ORDER BY TimeID ASC ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS c
                FROM c2
            ) i2
               ON i2.a = i.PartitionID
                  AND i2.b = i.TimeID;

SELECT * from #input;

Окончательный результат

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...