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
和每个 key
的 values
。如果日期不是已知日期,比如 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
代替)。
我在 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
和每个 key
的 values
。如果日期不是已知日期,比如 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
代替)。