查找和删除及时关闭的记录

时间:2019-07-08 14:50:35

标签: sqlite

我正在将温度记录到sqlite db,传感器每40秒发送一次〜6读数突发,以确保收到一个读数。通过将唯一属性添加到日期字段,我消除了大多数重复项。但是,有时时钟在猝发期间滴答1秒,因此我的记录相距约1秒。我想每40秒一次仅保留一次读数。我如何找到(并删除)这些记录?

insDate             id  temp    humidity 
2019-07-08 11:34:07 176 41.36   70.0 
2019-07-08 11:34:46 176 41.36   70.0 
2019-07-08 11:34:47 176 41.36   70.0 
2019-07-08 11:35:26 176 41.36   70.0 
2019-07-08 11:36:05 176 41.36   70.0 
2019-07-08 11:36:06 176 41.36   70.0 
2019-07-08 11:36:45 176 41.36   70.0

2 个答案:

答案 0 :(得分:0)

假设每个相邻的40秒块始终总是正好有6个读数,那么不一定有6个读数组的开始和结束。我们可以尝试按40秒的块汇总读数,然后仅对每个块取MIN读数:

SELECT
    ts % 40 AS block,
    MIN(reading) AS reading
FROM yourTable
GROUP BY
    ts % 40
ORDER BY
    ts % 40;

之所以可行,是因为假设我们选择的最小值实际上属于“上一个”块,因为我们错误地猜测了边界。然后,该移位也将出现在下一个块中,然后在下一个块中,因此最后没有关系。

此答案假设时间读数在称为ts的列中,并且包含从纪元以来的秒数。

答案 1 :(得分:0)

为避免注释中讨论的问题,其中数学时间窗口(使用模运算符)可能会任意中断/拆分同一突发的读数,而我们可以检查相邻记录以获取连续读数之间的时间延迟。问题的详细内容意味着与突发之间的延迟(约40秒)相比,同一突发记录中的读取可能会在很短的时间内(几秒钟内)发生。因此,要使每个猝发读取一次读数,请仅选择对下一条记录有较长延迟的记录,大约2到40秒之间……我有点随意选择10。

幸运的是,sqlite支持窗口功能,该功能允许使用基本SQL查询比较相邻的行,而无需在SQL之外编写任何脚本。

WITH sensorExt AS (
       SELECT *, 
              strftime('%s', insDate) AS tsec --Convert to seconds since 1970-01-01 00:00:00
       FROM sensor )
SELECT *
FROM -- Must use subquery in order to apply WHERE conditions to window function results
  (SELECT sensorExt.*,
         (lead(tsec) OVER (ORDER BY insDate ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING))
          - tsec as postspan -- Calculate difference between following row seconds
   FROM sensorExt
   ORDER BY sensorExt.insDate) AS sensorExt2
WHERE
   -- Only keep rows which are at end of "burst" with large delay to next record 
   -- coalesce() is called to handle/include the null value of the last record.
   coalesce(postspan, 11) > 10

注1 :我更喜欢在可能的情况下使用公用表表达式(CTE; WITH子句)代替子查询,但是似乎存在一个错误CTE中的>“窗口函数” (即OVER子句),因此我不得不恢复为子查询。否则,我将使用一系列CTE表来代替混合结构。

注释2 :使用标准的聚合SQL查询,也可以在没有窗口函数的情况下完成此操作,但是我认为至少需要3个嵌套子查询集才能获得相邻行之间的差异