Oracle имеет различные функции для линейной интерполяции.REGR_SLOPE
и REGR_INTERCEPT
полезны здесь.
Хитрость в вашем случае заключается в том, что это не линейная регрессия между значением и годом.Это линейная регрессия между значением и номером строки в группе стран.Поэтому нам нужно вычислить этот номер строки, прежде чем мы сможем вычислить интерполяцию.
with input_data (country, year, value) AS (
SELECT 'A', 2000, 1.5 FROM DUAL UNION ALL
SELECT 'A', 2001, 2.5 FROM DUAL UNION ALL
SELECT 'A', 2002, null FROM DUAL UNION ALL
SELECT 'A', 2003, 4.5 FROM DUAL UNION ALL
SELECT 'B', 2000, null FROM DUAL UNION ALL
SELECT 'B', 2000, null FROM DUAL UNION ALL
SELECT 'B', 2002, 5.3 FROM DUAL UNION ALL
SELECT 'B', 2003, 6.3 FROM DUAL UNION ALL
SELECT 'C', 2000, 1 FROM DUAL UNION ALL
SELECT 'C', 2001, null FROM DUAL UNION ALL
SELECT 'C', 2002, null FROM DUAL UNION ALL
SELECT 'C', 2003, 4 FROM DUAL
), ordered_input as (
SELECT
i.*,
row_number() over ( partition by country order by year) rn
FROM input_data i
)
SELECT
country,
year,
value,
rn * regr_slope(value, rn) over ( partition by country) +
regr_intercept(value, rn) over ( partition by country)
as interpolated_value
FROM ordered_input
ORDER BY country, year, rn;
+---------+------+-------+--------------------+
| COUNTRY | YEAR | VALUE | INTERPOLATED_VALUE |
+---------+------+-------+--------------------+
| A | 2000 | 1.5 | 1.5 |
| A | 2001 | 2.5 | 2.5 |
| A | 2002 | | 3.5 |
| A | 2003 | 4.5 | 4.5 |
| B | 2000 | | 3.3 |
| B | 2000 | | 4.3 |
| B | 2002 | 5.3 | 5.3 |
| B | 2003 | 6.3 | 6.3 |
| C | 2000 | 1 | 1 |
| C | 2001 | | 2 |
| C | 2002 | | 3 |
| C | 2003 | 4 | 4 |
+---------+------+-------+--------------------+