【问题标题】:SQL query with linear interpolation and Group By具有线性插值和 Group By 的 SQL 查询
【发布时间】:2021-03-30 05:18:28
【问题描述】:

我在 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 日(2020 年 2 月 1 日)获得 values,预期的输出是

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

其中 4.875 是 4.5(2020 年 1 月 1 日的值)和 6(2020 年 5 月 1 日的值)之间的线性插值。我手动将其评估为(y - 4.5) / (2 - 1) = (6 - 4.5) / (5 - 1)(更多参考请参见linear interpolation)。

3.7 相同

我怎样才能通过一个查询来实现(如果可能)?

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

更新 - 基于 PrestoDB 的 Athena 不支持 JOIN LATERAL,所以我不能考虑这个选项

【问题讨论】:

    标签: sql greatest-n-per-group presto amazon-athena lateral-join


    【解决方案1】:

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

    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 代替)。

    【讨论】:

    • 感谢您的回复!我花了一段时间在 Athena 中运行此查询返回 500 错误。然后我联系了他们的支持,他们告诉我 Athena 没有实现 JOIN LATERAL,因为它基于 PrestoDB(而它在 PrestoSQL 中可用)。所以这个解决方案不适用于 Athena。
    • @70ny:横向连接只是为了方便。查看我的编辑。
    • 感谢更新!我了解您的第二个查询,但这只会返回一行,而我每个键需要一行。 limit 1 导致只获取一个元素,而不是每个键一个元素(我应该在您的第一个建议查询中也注意到这一点)
    • @70ny:好的。我更改了第二个查询。
    猜你喜欢
    • 1970-01-01
    • 2019-01-21
    • 2018-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多