【问题标题】:How do I produce a time interval query in SQLite?如何在 SQLite 中生成时间间隔查询?
【发布时间】:2009-07-26 12:47:59
【问题描述】:

我有一个基于事件的表,我想生成一个查询,按分钟查询正在发生的事件数。

例如,我有一个像这样的事件表:

CREATE TABLE events (
     session_id  TEXT,
     event       TEXT,
     time_stamp  DATETIME
)

我已将其转换为以下类型的表格:

CREATE TABLE sessions (
     session_id    TEXT,
     start_ts      DATETIME,
     end_ts        DATETIME,
     duration      INTEGER
);

现在我想创建一个查询,该查询将按特定分钟内活跃的会话数对会话进行分组。我基本上会得到类似的东西:

TIME_INTERVAL ACTIVE_SESSIONS
------------- ---------------
18:00         1
18:01         5
18:02         3
18:03         0
18:04         2

【问题讨论】:

  • 如果已经有了“start_ts”和“end_ts”,“duration”是什么意思?
  • 我本可以忽略它......这不是问题的日耳曼。在我的实际情况中,我确实使用了类似的方法来避免在对持续时间进行查询时计算查询的差异。
  • 精确计算直到下一次更改的间隔不是更好吗?这些行看起来像“18:00:32 | 18:04:17 | 1”,计算起来会容易得多。这种“开始|结束|计数”的信息样式可以更容易地绘制图表等。
  • 恐怕你已经失去了我。在一天结束时,我需要能够在一段时间内绘制在给定时间段(例如分钟)内有多少“会话”处于活动状态。虽然我很欣赏这些想法,但恐怕我正在寻找我提出的问题的答案,对不起......
  • 这正是我提出的答案所提供的。那有什么问题?我没有实施我的额外“开始|结束|计数”提案。

标签: sql sqlite


【解决方案1】:

好的,我想我得到了更多我想要的东西。它不考虑空的间隔,但它足以满足我的需要。

select strftime('%Y-%m-%dT%H:%M:00.000',start_ts) TIME_INTERVAL, 
    (select count(session_id) 
      from sessions s2 
      where strftime('%Y-%m-%dT%H:%M:00.000',s1.start_ts) between s2.start_ts and s2.end_ts) ACTIVE_SESSIONS
   from sessions s1
   group by strftime('%Y-%m-%dT%H:%M:00.000',start_ts);

这将在数据涵盖的时间段内每分钟生成一行,并计算已启动 (start_ts) 但尚未完成 (end_ts) 的会话数。

【讨论】:

    【解决方案2】:

    PostgreSQL 允许以下查询。

    与您的示例相反,这会返回当天的附加列,并省略未发生任何事情的分钟数 (count=0)。

    select
        day, hour, minute, count(*)
    from
        (values ( 0),( 1),( 2),( 3),( 4),( 5),( 6),( 7),( 8),( 9),
                (10),(11),(12),(13),(14),(15),(16),(17),(18),(19),
                (20),(21),(22),(23),(24),(25),(26),(27),(28),(29),
                (30),(31),(32),(33),(34),(35),(36),(37),(38),(39),
                (40),(41),(42),(43),(44),(45),(46),(47),(48),(49),
                (50),(51),(52),(53),(54),(55),(56),(57),(58),(59))
         as minutes (minute),
        (values ( 0),( 1),( 2),( 3),( 4),( 5),( 6),( 7),( 8),( 9),
                (10),(11),(12),(13),(14),(15),(16),(17),(18),(19),
                (20),(21),(22),(23))
         as hours (hour),
        (select distinct cast(start_ts as date) from sessions
         union
         select distinct cast(end_ts as date) from sessions)
         as days (day),
        sessions
    where
        (day,hour,minute)
        between (cast(start_ts as date),extract(hour from start_ts),extract(minute from start_ts))
            and (cast(end_ts as date),  extract(hour from end_ts),  extract(minute from end_ts))
    group by
        day, hour, minute
    order by
        day, hour, minute;

    【讨论】:

    • 您可以使用扩展名 generate_series。范围(开始,结束,步骤)代替“值(1),(2),...”:.load generate_series.dllSELECT hours.value, minute.value from generate_series(1,59,1) as minute; JOIN generate_series(1,24,1) as hours
    【解决方案3】:

    这不完全是您的查询,但我认为它可能会有所帮助。您是否查看过 SQLite R-Tree module?这将允许您在开始/停止时间创建一个虚拟索引:

    CREATE VIRTUAL TABLE sessions_index USING rtree (id, start, end);
    

    然后你可以通过以下方式搜索:

    SELECT * FROM sessions_index WHERE end >= <first minute> AND start <= <last minute>;
    

    【讨论】:

      猜你喜欢
      • 2012-03-27
      • 1970-01-01
      • 1970-01-01
      • 2023-02-21
      • 1970-01-01
      • 1970-01-01
      • 2022-01-18
      • 2020-02-14
      • 1970-01-01
      相关资源
      最近更新 更多