SQL 使用线性插值和分组依据进行查询

SQL query with linear interpolation and Group By

我在 AWS 上有一个数据湖,使用 Athena 查询,具有以下结构和样本数据

Key |     Date      |  Value
----+---------------+-------
 a  |   01/01/2020  |  4.5
 a  |   05/01/2020  |  6
 a  |   06/01/2020  |  3.2
 b  |   01/01/2020  |  2.4
 b  |   03/01/2020  |  5

我想 运行 查询以提取特定 date 和每个 keyvalues。如果日期不是已知日期,比如 99% 的时间,值应该作为两个最接近的日期的线性插值返回。

为简单起见,

Dates 在这里以 dd/mm/YYYY 格式报告,但在数据湖中存储为时间戳。

结果示例

如果我想获得 1 月 2 日 (02/01/2020) 的 values,则预期输出为

Key |     Date      |  Value
----+---------------+-------
 a  |   02/01/2020  |  4.875
 b  |   02/01/2020  |  3.70

其中 4.875 是 4.5(01/01/2020 的值)和 6(05/01/2020 的值)之间的线性插值。我已将其手动评估为 (y - 4.5) / (2 - 1) = (6 - 4.5) / (5 - 1)(有关更多参考,请参阅 linear interpolation)。

3.7 相同

如何通过一个查询实现这一点(如果可能)?

假设:从我们搜索的点开始,我们总是有一个更小和更大的日期。

Update - 基于 PrestoDB 的 Athena 不支持 JOIN LATERAL,所以这不是我可以考虑的选项

这可能是横向连接的好地方:

select d.dt, 
    case 
        when n.date = p.date then p.value
        else p.value + (n.value - p.value) / datediff('day', n.date, p.date)
    end as new_value
from (select date '2020-04-01') d(date)
cross join lateral (
    select t.* from mytable t where t.date <= d.date order by t.date desc limit 1
) p  -- "previous" value
cross join lateral (
    select t.* from mytable t where t.date >= d.date order by t.date limit 1
) n  -- "next" value

我们可以编写没有横向连接的查询:

select date '2020-04-01' as dt, p.k,
    case 
        when n.date = p.date then p.value
        else p.value + (n.value - p.value) / datediff('day', n.date, p.date)
    end as new_value
from (
    select t.*, 
        row_number() over(partition by k order by date desc) as rn
    from mytable t
    where date <= '2020-04-01'
) p
inner join (
    select t.*, 
        row_number() over(partition by k order by date) as rn
    from mytable t
    where date >= '2020-04-01'
) n on n.k = p.k
where p.rn = 1 and n.rn = 1

这也概括了查询,因此它可以一次处理多个键(key 是语言关键字,我用 k 代替)。