【问题标题】:How to join generated datetimes with data in SQLite database?如何将生成的日期时间与 SQLite 数据库中的数据连接起来?
【发布时间】:2022-01-08 02:35:28
【问题描述】:

我有一个表格,其中包含来自这样创建的传感器的数据:

CREATE TABLE IF NOT EXISTS "aqi" (
  "time" datetime,
  "pm25" real,
  "pm10" real
);

当传感器运行时,它每秒向服务器发送数据(将其写入数据库)。但是当传感器没有运行时,数据库中的数据会出现这样的“空白”(我已将time 列重写为可读格式和时区GMT+01,将原始数据留在括号中):

time pm25 pm10
... ... ...
2021-12-28 18:44 (1640713462) 9.19 9.27
2021-12-28 18:45 (1640713522) 9.65 9.69
2021-12-28 18:46 (1640713582) 9.68 9.76
2021-12-29 10:17 (1640769421) 7.42 7.42
2021-12-29 10:18 (1640769481) 7.94 7.98
2021-12-29 10:19 (1640769541) 7.42 7.43
... ... ...

我想创建一个查询,选择过去 24 小时的数据,如果表中没有当前数据,则将 pm25 和 pm10 输出为 NULL时间。所以上面的表格应该是这样的:

time pm25 pm10
... ... ...
2021-12-28 18:44 (1640713462) 9.19 9.27
2021-12-28 18:45 (1640713522) 9.65 9.69
2021-12-28 18:46 (1640713582) 9.68 9.76
2021-12-28 18:47 (1640713642) NULL NULL
2021-12-28 18:48 (1640713702) NULL NULL
2021-12-28 18:49 (1640713762) NULL NULL
... ... ...
2021-12-29 10:14 (1640769262) NULL NULL
2021-12-29 10:15 (1640769322) NULL NULL
2021-12-29 10:16 (1640769382) NULL NULL
2021-12-29 10:17 (1640769421) 7.42 7.42
2021-12-29 10:18 (1640769481) 7.94 7.98
2021-12-29 10:19 (1640769541) 7.42 7.43
... ... ...

我不介意秒数会不会因为时间的产生而不同...


在过去 24 小时内,我尝试使用来自 https://stackoverflow.com/a/32987070 的代码生成 time,并且效果如我所愿:

WITH RECURSIVE dates(generated_time) AS (
  VALUES(datetime('now', '-1 minute', 'localtime'))
  UNION ALL
  SELECT datetime(generated_time, '-1 minute')
  FROM dates
  LIMIT 1440
)
SELECT strftime('%Y-%m-%d %H:%M', datetime(generated_time)) AS time
FROM dates;

但我不知道如何从传感器(列pm25、pm10)添加(JOIN)数据以进行上述查询...我尝试了一些方法,但它输出了 0 行:

WITH RECURSIVE dates(generated_time) AS (
  VALUES(datetime('now', '-1 minute', 'localtime'))
  UNION ALL
  SELECT datetime(generated_time, '-1 minute')
  FROM dates
  LIMIT 1440
)
SELECT
    strftime('%Y-%m-%d %H:%M', datetime(generated_time)) AS generated_time,
    pm25, 
    pm10
FROM
    dates
    INNER JOIN aqi ON generated_time = strftime('%Y-%m-%d %H:%M', datetime(aqi.time));

可能这是很明显的事情,我错过了,但我不知道:/


编辑:
正如@DrummerMann 指出的那样,它与LEFT JOIN 一起工作,但执行查询大约需要一分钟(在数据库中大约有14000 个值):

WITH RECURSIVE dates(time) AS (
  VALUES(datetime('now', '-1 minute', 'localtime'))
  UNION ALL
  SELECT datetime(time, '-1 minute')
  FROM dates
  LIMIT 1440
)
SELECT
    dates.time,
    aqi.pm25, 
    aqi.pm10
FROM
    dates
    LEFT JOIN aqi ON strftime('%Y-%m-%d %H:%M', datetime(dates.time)) = strftime('%Y-%m-%d %H:%M', datetime(aqi.time, 'unixepoch', 'localtime'))
    ORDER BY dates.time;

有没有更好的方法来做到这一点?

【问题讨论】:

  • 你签出LEFT JOIN了吗? w3schools.com/sql/sql_join_left.asp
  • 我发现,我忘记将'unixepoch', 'localtime' 添加到datetime 转换,所以我用工作LEFT JOIN 代码编辑了我的问题,但是执行查询需要一整分钟。 .
  • 将 strftime('%Y-%m-%d %H:%M', datetime(dates.time)) 移至 cte。在 ON 子句中使用预先计算的值应该会快一些。

标签: sql sqlite datetime left-join recursive-query


【解决方案1】:

试试这个版本的 cte,它使用整数 unix 时间戳,其中秒数被剥离,并且连接的 ON 子句中没有函数:

WITH RECURSIVE dates(generated_time) AS (
  SELECT strftime('%s', 'now', '-1 minute', 'localtime') / 60 * 60
  UNION ALL
  SELECT generated_time - 60
  FROM dates
  LIMIT 1440
)
SELECT strftime('%Y-%m-%d %H:%M', d.generated_time, 'unixepoch', 'localtime') AS generated_time,
       a.pm25, 
       a.pm10
FROM dates d LEFT JOIN aqi a
ON d.generated_time = a.time / 60 * 60;

【讨论】:

  • 谢谢,它可以工作,但是第二行查询应该像这样SELECT strftime('%s', 'now', '-1 minute') / 60 * 60,因为使用'localtime' 选项time 将在输出中移动...现在大约需要 3.5 秒执行力,这确实是一个很好的改进:)
  • @BelKed 我使用 'localtime' 修饰符是因为您的代码中有它,而且我假设您表中的时间戳是本地化的。
  • 哦,我明白了...我在表中有 UTC unix 时间戳,因此它需要转换为 'localtime',但在您的回答中,您在最后一行使用 a.time 而不转换为 @987654328 @,所以这可能是时移的原因......
猜你喜欢
  • 1970-01-01
  • 2012-02-10
  • 2019-09-15
  • 2015-09-11
  • 1970-01-01
  • 2015-06-18
  • 1970-01-01
  • 1970-01-01
  • 2010-12-28
相关资源
最近更新 更多