生成具有最接近值的缺席日期

问题描述 投票:0回答:2

有一个表(mileage_event)显示所有汽车的里程。 包含以下列: 创建时间 - 日期, car_id - 汽车 ID, car_mileage - 汽车的里程

值得考虑的是,并非所有日子都有数据。 例如:

汽车 ID 创建于 汽车_里程
d016e61c5326-f246894a 2023-05-22 100000
d016e61c5326-f246894a 2023-05-26 105000
d016e61c5326-f246894a 2023-05-27 110000

如您所见,在 2023-05-22 和 2023-05-26 之间(即缺席 3 天)这辆车没有行。说明这几天车子没有开过。

我想要什么:生成缺失的天数并为其添加最接近的里程值。

(注:Exasol数据库)
结果:

汽车 ID 创建于 汽车_里程
d016e61c5326-f246894a 2023-05-22 100000
d016e61c5326-f246894a 2023-05-23 100000
d016e61c5326-f246894a 2023-05-24 100000
d016e61c5326-f246894a 2023-05-25 100000
d016e61c5326-f246894a 2023-05-26 105000
d016e61c5326-f246894a 2023-05-27 110000

提前致谢!

sql date window-functions exasol
2个回答
0
投票

啊,总是很高兴看到有人问一个合理的问题并且人们评论“你应该用谷歌搜索它”。

您可以通过利用公共表表达式 (CTE)、窗口函数以及连接一系列日期来实现此目的。总体策略是:

生成一系列涵盖您感兴趣范围的日期。 对于每个 car_id,使用 LEFT JOIN 将此日期系列与您现有的里程数据结合起来。 使用窗口函数来填充缺失的里程数据。 我会这样做:

-- Create a CTE with a series of dates. Adjust the start and end dates as needed.
WITH date_series AS (
    SELECT CAST('2023-05-22' AS DATE) + ROW_NUMBER() OVER() - 1 AS created_at
    FROM (SELECT 1 FROM DUAL CONNECT BY LEVEL <= 30) -- Generating 30 days, adjust this number as needed
),

--  LEFT JOIN the date series with your mileage data and use LAG() to fill in gaps.
combined AS (
    SELECT 
        m.car_id,
        d.created_at,
        COALESCE(m.car_mileage, 
                 LAG(m.car_mileage, 1) OVER (PARTITION BY m.car_id ORDER BY d.created_at)) AS car_mileage
    FROM date_series d
    LEFT JOIN mileage_event m ON d.created_at = m.created_at
)

-- Get result
SELECT * FROM combined WHERE car_id IS NOT NULL ORDER BY car_id, created_at

我希望能够回答您的问题并且有效。如果您需要更多帮助,请告诉我。


0
投票

我不知道 Exasol 语法。在 SQL 中,您通常会使用递归查询来填补一系列空白。您要做的就是获取每一行,查看其下一行(如果有),这样您就知道要添加多少天。然后根据需要添加任意多的行。

以下是Oracle语法。在 Exasol 中,您可能需要添加关键字

RECURSIVE
或将间隔更改为
interval '1 days'
等。您可能可以在文档中找到它。

with cte (car_id, created_at, car_mileage, next_created_at) as
(
  select
    car_id, created_at, car_mileage,
    lead(created_at) over (partition by car_id order by created_at) as next_created_at
  from mytable
  union all
  select car_id, created_at + interval '1' day, car_mileage, next_created_at
  from cte
  where created_at + interval '1' day < next_created_at
)
select car_id, created_at, car_mileage
from cte
order by car_id, created_at;

演示:https://dbfiddle.uk/61_Ht136

© www.soinside.com 2019 - 2024. All rights reserved.