Пример с линейной интерполяцией.
WITH
cte1 AS ( SELECT t1.ts, t1.val,
t2.ts ts_before, t2.val val_before,
t3.ts ts_after, t3.val val_after
FROM test t1
JOIN test t2 ON t1.ts >= TIMESTAMP(t2.ts, @delta)
JOIN test t3 ON t1.ts <= TIMESTAMP(t3.ts, @delta) ),
cte2 AS ( SELECT *,
ROW_NUMBER() OVER (PARTITION BY ts ORDER BY ts_before DESC) rn_before,
ROW_NUMBER() OVER (PARTITION BY ts ORDER BY ts_after ASC) rn_after
FROM cte1 )
SELECT ts,
val,
ts_before,
val_before,
ts_after,
val_after,
CASE WHEN val_after = val_before
THEN val_before
ELSE val_before + (val_after - val_before) / TIMESTAMPDIFF(SECOND, ts_after, ts_before) * TIMESTAMPDIFF(SECOND, ts, TIMESTAMP(ts_before, @delta))
END val_approximated
FROM cte2
WHERE ts > '2021-01-02'
AND rn_before = 1
AND rn_after = 1
DEMO fiddle с некоторыми пояснениями.
Тормозить, конечно, на большом массиве будет нещадно - так что неплохо бы ещё в первом CTE по всем трём копиям задать вменяемые границы от и до...
Не имел дела раньше с оконными функциями в MySQL.
А придётся. И не просто "иметь дело", а хорошо изучить, до полного понимания.