【问题标题】:How can I fill in/interpolate mising timestamps in an SQLite query?如何在 SQLite 查询中填写/插值缺失的时间戳?
【发布时间】:2021-01-11 06:10:08
【问题描述】:

我在表格中记录了一堆 GPS 轨迹。由于 GPS 记录代码中的错误,每个时间戳的小数部分不正确(并且重复)。我想创建一个查询,查找具有相同时间戳的第一条和最后一条记录,并确定每次翻转之间的记录数(以整秒为单位)。这可用于确定每条记录之间的增量。我想用它来插入时间戳的丢失/不正确的小数部分。

现有表

| id | timestamp                  |
|----|----------------------------|
| 1  | 2020-09-06 15:08:21.128344 |
| 2  | 2020-09-06 15:08:21.128344 |
| 3  | 2020-09-06 15:08:21.128344 |
| 4  | 2020-09-06 15:08:22.128344 |

期望的输出

| id | timestamp                  |
|----|----------------------------|
| 1  | 2020-09-06 15:08:21.0      |
| 2  | 2020-09-06 15:08:21.25     |
| 3  | 2020-09-06 15:08:21.75     |
| 4  | 2020-09-06 15:08:22.0      |

在阅读Select first row in each GROUP BY group 之后,我想出了如何在每个组中获取具有相同时间戳的第一行。

WITH A AS (
    SELECT ROW_NUMBER() OVER (PARTITION BY time ORDER BY id) as rn, *
    FROM gps_points
) SELECT * FROM A WHERE rn=1 ORDER BY id;

我希望通过添加生成时间戳 (rn -1) * datetime((round(julianday(first_row.timestamp) * 86400) / 86400)) 其中first_row 是相同时间戳的第一行,delta1/(3 repeated timestamps + 1)

这可以用这张表来解释。

| id | rn       | timestamp                              |
|----|----------|----------------------------------------|
| 1  | 0        | 2020-09-06 15:08:21.0 + 0 * delta      |
| 2  | 1        | 2020-09-06 15:08:21.0 + 1 * delta      |
| 3  | 2        | 2020-09-06 15:08:21.0 + 2 * delta      |
| 4  | 0        | 2020-09-06 15:08:22.0 + 0 * delta      |

我无法将上述查询集成到一个更大的查询中来满足我的需求。也许我应该写一些 python 代码来做这件事,但我想提高我的 SQL 知识并一举做到这一点。

【问题讨论】:

  • 所以您总是希望每次重复添加 0.25 秒?如果有 10 条记录具有相同的时间戳,结果会怎样?
  • 在这种情况下,它将是 1/11 秒,以防我的逻辑出现一个错误。在我的实际数据中,几乎每个集群都有 25 条记录。
  • 为什么 id = 3 的时间戳在预期输出 ....22.75 中?对于 id = 4,它是 22.0?
  • 我的错误。解决了这个问题。
  • 现在为什么 15:08:22.128344 变成 2020-09-06 15:08:23.0?只有 1 15:08:22.128344。为什么会增加到 2020-09-06 15:08:23.0?

标签: sql sqlite window-functions


【解决方案1】:

使用ROW_NUMBER()COUNT() 窗口函数:

WITH cte AS (
  SELECT *,
    ROW_NUMBER() OVER (PARTITION BY timestamp ORDER BY ID) rn,
    COUNT(*) OVER (PARTITION BY timestamp) counter
  FROM tablename  
)
SELECT id,
       DATETIME(timestamp) || '.' || 
       SUBSTR('00' || ((rn - 1) * (100 / (counter + 1))), -2) timestamp
FROM cte

请参阅demo
结果:

> id | timestamp             
> -: | :---------------------
>  1 | 2020-09-06 15:08:21.00
>  2 | 2020-09-06 15:08:21.25
>  3 | 2020-09-06 15:08:21.50
>  4 | 2020-09-06 15:08:22.00

我使用counter + 1 进行除法,以获得您预期的结果,但我相信正确的做法是不使用+1

WITH cte AS (
  SELECT *,
    ROW_NUMBER() OVER (PARTITION BY timestamp ORDER BY ID) rn,
    COUNT(*) OVER (PARTITION BY timestamp) counter
  FROM tablename  
)
SELECT id,
       DATETIME(timestamp) || '.' || 
       SUBSTR('00' || ((rn - 1) * (100 / counter)), -2) timestamp
FROM cte 

请参阅demo
结果:

> id | timestamp             
> -: | :---------------------
>  1 | 2020-09-06 15:08:21.00
>  2 | 2020-09-06 15:08:21.33
>  3 | 2020-09-06 15:08:21.66
>  4 | 2020-09-06 15:08:22.00

【讨论】:

    【解决方案2】:

    这是一种选择:

    select t.*,
        substr(timestamp, 1, 20) || (
            1000 * (row_number() over(partition by timestamp order by id) - 1) 
            / (count(*) over(partition by timestamp))
        ) new_timestamp
    from mytable t
    

    这个想法是在同一秒内平均分配具有相同时间戳的记录。如果只有一条记录,则截断其小数秒。

    这给了你 3 个小数秒。如果您愿意,可以将乘数从 1000 更改为其他值。

    我推测您希望将逻辑扩展到属于同一秒的记录,而不仅仅是完美的时间戳重复。这只是partition by 子句的细微变化:

    select t.*,
        substr(timestamp, 1, 20) || (
            1000 * (row_number() over(partition by datetime(timestamp) order by id) - 1) 
            / (count(*) over(partition by datetime(timestamp)))
        ) new_timestamp
    from mytable t
    

    Demo on DB Fiddle

    编号 |时间戳 |新时间戳 -: | :------------------------- | :------------------------ 1 | 2020-09-06 15:08:21.128344 | 2020-09-06 15:08:21.0 2 | 2020-09-06 15:08:21.128344 | 2020-09-06 15:08:21.333 3 | 2020-09-06 15:08:21.128344 | 2020-09-06 15:08:21.666 4 | 2020-09-06 15:08:22.128344 | 2020-09-06 15:08:22.0

    【讨论】:

    • 这几乎可以工作,但在小数部分缺少零填充。我不知道如何在评论框中粘贴一个大代码块。
    猜你喜欢
    • 2019-03-08
    • 2020-06-18
    • 1970-01-01
    • 2020-10-23
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 2018-10-08
    • 2021-12-26
    相关资源
    最近更新 更多