You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过SQL将设备停留时间段拆分为每5分钟时间点记录?

生成5分钟间隔的设备房间记录解决方案

核心思路

要实现需求,需要把每个设备的停留时间段拆分为5分钟整间隔的时间点(如XX:00、XX:05、XX:10),筛选出落在设备在房间时间段内的时间点,再关联设备和房间信息。


针对PostgreSQL的SQL实现

假设你的objects表中start_time和end_time是字符串格式(如31.10.2022 10:05:00),可以用以下查询:

SELECT
  o.modellnumber AS modell,
  o.roomnumber AS room,
  TO_CHAR(gs.time_point, 'DD.MM.YYYY HH24:MI:SS') AS time
FROM
  objects o
CROSS JOIN LATERAL
  generate_series(
    -- 计算符合要求的起始5分钟时间点
    CASE
      WHEN date_trunc('minute', to_timestamp(o.start_time, 'DD.MM.YYYY HH24:MI:SS')) 
           - (EXTRACT(minute FROM to_timestamp(o.start_time, 'DD.MM.YYYY HH24:MI:SS')) %5)*interval '1 minute' 
           < to_timestamp(o.start_time, 'DD.MM.YYYY HH24:MI:SS')
      THEN date_trunc('minute', to_timestamp(o.start_time, 'DD.MM.YYYY HH24:MI:SS')) 
           - (EXTRACT(minute FROM to_timestamp(o.start_time, 'DD.MM.YYYY HH24:MI:SS')) %5)*interval '1 minute' 
           + interval '5 minutes'
      ELSE date_trunc('minute', to_timestamp(o.start_time, 'DD.MM.YYYY HH24:MI:SS')) 
           - (EXTRACT(minute FROM to_timestamp(o.start_time, 'DD.MM.YYYY HH24:MI:SS')) %5)*interval '1 minute'
    END,
    to_timestamp(o.end_time, 'DD.MM.YYYY HH24:MI:SS'),
    interval '5 minutes'
  ) gs(time_point)
ORDER BY
  modell, room, gs.time_point;

代码解释

  • to_timestamp(o.start_time, 'DD.MM.YYYY HH24:MI:SS'):把字符串时间转成数据库可计算的timestamp类型,指定格式匹配你的数据(日.月.年 时:分:秒)。
  • date_trunc('minute', ...):将时间截断到分钟级,配合%5计算最近的5分钟整时间点。
  • CASE语句:确保起始时间点不早于设备进入房间的时间,避免出现设备还没进入就记录的情况。
  • generate_series:生成从起始点到设备离开时间的5分钟间隔时间序列。
  • TO_CHAR(...):把timestamp类型的时间点转回你需要的字符串格式。

针对MySQL的SQL实现

MySQL没有generate_series函数,需要用递归CTE生成时间序列:

WITH RECURSIVE time_series AS (
  SELECT
    o.modellnumber AS modell,
    o.roomnumber AS room,
    -- 计算起始5分钟时间点
    CASE
      WHEN DATE_FORMAT(STR_TO_DATE(o.start_time, '%d.%m.%Y %H:%i:%s'), '%Y-%m-%d %H:00:00') 
           + INTERVAL FLOOR(MINUTE(STR_TO_DATE(o.start_time, '%d.%m.%Y %H:%i:%s'))/5)*5 MINUTE 
           < STR_TO_DATE(o.start_time, '%d.%m.%Y %H:%i:%s')
      THEN DATE_FORMAT(STR_TO_DATE(o.start_time, '%d.%m.%Y %H:%i:%s'), '%Y-%m-%d %H:00:00') 
           + INTERVAL FLOOR(MINUTE(STR_TO_DATE(o.start_time, '%d.%m.%Y %H:%i:%s'))/5)*5 MINUTE 
           + INTERVAL 5 MINUTE
      ELSE DATE_FORMAT(STR_TO_DATE(o.start_time, '%d.%m.%Y %H:%i:%s'), '%Y-%m-%d %H:00:00') 
           + INTERVAL FLOOR(MINUTE(STR_TO_DATE(o.start_time, '%d.%m.%Y %H:%i:%s'))/5)*5 MINUTE
    END AS time_point,
    STR_TO_DATE(o.end_time, '%d.%m.%Y %H:%i:%s') AS end_time
  FROM objects o
  UNION ALL
  SELECT
    modell,
    room,
    time_point + INTERVAL 5 MINUTE,
    end_time
  FROM time_series
  WHERE time_point + INTERVAL 5 MINUTE <= end_time
)
SELECT 
  modell, 
  room, 
  DATE_FORMAT(time_point, '%d.%m.%Y %H:%i:%s') AS time
FROM time_series
ORDER BY modell, room, time_point;

注意事项

  • 确保时间格式参数和你的数据完全匹配,比如如果你的时间是YYYY-MM-DD格式,要调整to_timestamp或STR_TO_DATE里的格式字符串。
  • 如果你的时间字段已经是timestamp/datetime类型,可以去掉字符串转时间的步骤,直接使用字段本身。

内容的提问来源于stack exchange,提问作者JazCodes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 16:05:34