从可变起点线性外推值至 0
Linear extrapolate values down to 0 from variable starting points
我想构建一个查询,它允许我从最后一个已知值开始灵活地线性推断一个数字到 Age 0。 table(见下文)有两列,Age 和 Volume。我最后已知的体积是 11 岁时的 321.60,我如何以每年的步长将 321.60 线性外推到 0 岁?另外,我想以允许年龄改变的方式设计查询。例如,在另一个场景中,最后一个体积是 27 岁。我一直在试验 lead 函数,结果我可以推断出 10 岁时的体积,但该函数不允许我向下推断到 0。我怎么能设计一个查询,(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 |
+-----+--------+-------------+
对于这种事情,您可以使用带空 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()
会忽略空值。
如果我假设 0
处的值为 0
,那么您可以使用简单的算术运算。这似乎适用于您的情况:
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;
Here 是一个 db<>fiddle
我想构建一个查询,它允许我从最后一个已知值开始灵活地线性推断一个数字到 Age 0。 table(见下文)有两列,Age 和 Volume。我最后已知的体积是 11 岁时的 321.60,我如何以每年的步长将 321.60 线性外推到 0 岁?另外,我想以允许年龄改变的方式设计查询。例如,在另一个场景中,最后一个体积是 27 岁。我一直在试验 lead 函数,结果我可以推断出 10 岁时的体积,但该函数不允许我向下推断到 0。我怎么能设计一个查询,(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 |
+-----+--------+-------------+
对于这种事情,您可以使用带空 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()
会忽略空值。
如果我假设 0
处的值为 0
,那么您可以使用简单的算术运算。这似乎适用于您的情况:
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;
Here 是一个 db<>fiddle