Линейная экстраполяция значений до 0 от переменных начальных точек - PullRequest
0 голосов
/ 12 июля 2020

Я хочу создать запрос, который позволяет мне гибко линейно экстраполировать число до возраста 0, начиная с последнего известного значения. Таблица (см. Ниже) состоит из двух столбцов: «Возраст» и «Объем». Мой последний известный объем - 321,60 в возрасте 11 лет, как я могу линейно экстраполировать 321,60 до возраста 0 лет с шагом в год? Кроме того, я хотел бы разработать запрос таким образом, чтобы можно было изменять возраст. Например, в другом сценарии последний том находится в возрасте 27 лет. Я экспериментировал с функцией опережения, в результате я могу экстраполировать объем в возрасте 10 лет, но функция не позволяет мне экстраполировать его до нуля. Как я могу разработать запрос, который (A) позволяет мне проводить линейную экстраполяцию до возраста 0, а (B) является гибким и допускает разные отправные точки для линейной экстраполяции.

SELECT     [age], 
           [volume], 
           Concat(CASE WHEN volume IS NULL THEN ( Lead(volume, 1, 0) OVER (ORDER BY age) ) / ( age + 1 ) * 
           age END, volume) AS 'Extrapolate' 
    FROM   tbl_volume

+-----+--------+-------------+
| Age | Volume | Extrapolate |
+-----+--------+-------------+
|   0 | NULL   | NULL        |
|   1 | NULL   | NULL        |
|   2 | NULL   | NULL        |
|   3 | NULL   | NULL        |
|   4 | NULL   | NULL        |
|   5 | NULL   | NULL        |
|   6 | NULL   | NULL        |
|   7 | NULL   | NULL        |
|   8 | NULL   | NULL        |
|   9 | NULL   | NULL        |
|  10 | NULL   | 292.363     |
|  11 | 321.60 | 321.60      |
|  12 | 329.80 | 329.80      |
|  13 | 337.16 | 337.16      |
|  13 | 343.96 | 343.96      |
|  14 | 349.74 | 349.74      |
+-----+--------+-------------+

Ответы [ 2 ]

1 голос
/ 12 июля 2020

Если я предполагаю, что значение равно 0 при 0, то вы можете использовать простую арифметику c. Кажется, это работает в вашем случае:

select t.*,
       coalesce(t.volume, t.age * (t2.volume / t2.age)) as extrapolated_volume
from t cross join
     (select top (1) t2.*
      from t t2
      where t2.volume is not null
      order by t2.age asc
     ) t2;

Здесь - это db <> fiddle

0 голосов
/ 12 июля 2020

Вы можете использовать оконную функцию с пустым over() для такого рода вещей. В качестве тривиального примера:

create table t(j int, k decimal(3,2));
insert t values (1, null), (2, null), (3, 3), (4, 4);

select  j, j * avg(k / j) over ()       
from    t

Обратите внимание, что avg() игнорирует нули.

...