1

我有以下选择语句,其中我减去时间戳以了解卡车在某个位置停了多长时间:

 SELECT  f.id, f.imei as imei, f.speed as speed  FROM stops f, stops f2
 where f2.id = f.id-1
 and f.imei = 7466
 and hour(timediff(f2.timestamp,f.timestamp)) * 3600 +   minute(timediff(f2.timestamp,f.timestamp)) * 60 + second(timediff(f2.timestamp,f.timestamp)) > 240 
 and f.speed = 0
 and f2.timestamp >= '2013-08-20 00:00:00' 
 and f2.timestamp <= '2013-08-20 23:59:59'  
 order by f2.timestamp desc

用于计算停靠点的行:

id imei     timestamp               speed
1  7466     2013-08-20 13:19:00     30    
2  7466     2013-08-20 13:20:00     0 
3  7466     2013-08-20 13:24:30     20

因此,选择给出的结果是车辆 7466 停止了 4 分钟。

当行是这样的时候问题就来了:

id imei     timestamp               speed 
1  7466     2013-08-20 13:19:00     30     
2  7466     2013-08-20 13:20:00     0 
3  7466     2013-08-20 13:21:00     0 
4  7466     2013-08-20 13:22:00     0 
5  7466     2013-08-20 13:24:30     20

它不减去。我怎样才能得到结果时间?

4

3 回答 3

1

我相信这是正确的(请参阅SQL Fiddle来测试它):

SELECT
  s1.id AS stopped_row_id, MIN(s2.id) AS departed_row_id, TIMESTAMPDIFF(SECOND, s1.timestamp, MIN(s2.timestamp)) AS stopped_seconds
FROM
  stops AS s1
  JOIN stops AS s2 ON
    s1.imei = s2.imei
    AND s1.id < s2.id
    AND (s1.timestamp + INTERVAL 4 MINUTE) <= s2.timestamp
  JOIN stops AS s3 ON
    s1.imei = s2.imei
    AND s3.id = s1.id - 1
  LEFT JOIN stops AS s4 ON
    s1.imei = s2.imei
    AND s4.id BETWEEN (s1.id + 1) AND (s2.id - 1)
    AND s4.speed <> 0
WHERE
  s1.speed = 0
  AND s2.speed <> 0
  AND s3.speed <> 0
  AND s4.id IS NULL
  AND s1.imei = 7466 -- optional; query will also give results for all imei if wanted
  AND s1.timestamp BETWEEN '2013-08-20 00:00:00' AND '2013-08-20 23:59:59' -- optional, query will give results for entire table if wanted
GROUP BY
  s1.id,
  s1.timestamp

在此查询中,s1是“主”表。
s2连接以向所有行提供比ids 高至少 4 分钟的所有行(因此本质上,所有行都指示暂停的时间足够长,以使行 from应该进入最终结果集)。连接以确保其中的行是 0的第一行(对于您的示例,其中有0 组的行)。连接以确保在 和 的“选定”行之间没有非零速行。确保我们可以在未来获得 第一个时间戳s1timestamps1s2s1
s3s1speedspeed
s4s1s2
GROUP BYspeed通过使用 不为 0 MIN()


显然,这些行不是严格的降序或升序(即使 ID 是)。我已经修改了查询,只使用时间作为“排序机制”。请注意,这会使查询变得非常慢,您可能会更好地通过以@peterm 的样式排序表或解决方案。或者至少在idand上添加一个索引timestamp

SELECT
  s1.timestamp AS stopped_timestamp, MAX(s2.timestamp) as departed_timestamp, TIMESTAMPDIFF(SECOND, s1.timestamp, MAX(s2.timestamp)) AS stopped_seconds
FROM
  stops AS s1
  JOIN stops AS s2 ON
    s1.imei = s2.imei
    AND (s1.timestamp + INTERVAL 4 MINUTE) <= s2.timestamp
  JOIN stops AS s3 ON
    s1.imei = s2.imei
  LEFT JOIN stops AS s4 ON
    s1.imei = s2.imei
    AND s4.timestamp BETWEEN (s1.timestamp + INTERVAL 1 SECOND) AND (s2.timestamp - INTERVAL 1 SECOND)
    AND s4.speed <> 0
WHERE
  s1.speed = 0
  AND s2.speed <> 0
  AND s3.speed <> 0
  AND s4.id IS NULL
  AND s1.imei = 7466 -- optional; query will also give results for all imei if wanted
  AND s1.timestamp BETWEEN '2013-08-20 00:00:00' AND '2013-08-20 23:59:59' -- optional, query will give results for entire table if wanted
  AND s3.timestamp = (SELECT MAX(s5.timestamp) FROM stops AS s5 WHERE s5.timestamp < s1.timestamp)
GROUP BY
  s1.id,
  s1.timestamp
于 2013-08-20T00:22:31.623 回答
0

您要求一辆卡车停车时间超过 4 分钟(240 秒)。请参阅 SQL 查询的以下行。

hour(timediff(f2.timestamp,f.timestamp)) * 3600 + 
minute(timediff(f2.timestamp,f.timestamp)) * 60 + 
second(timediff(f2.timestamp,f.timestamp)) > 240

在下表中...

id imei     timestamp               speed     
1  7466     2013-08-20 13:20:00     0 
2  7466     2013-08-20 13:21:00     0 
3  7466     2013-08-20 13:22:00     0 
2  7466     2013-08-20 13:24:00     20

在这些对中,卡车的停留时间均未超过 4 分钟(240 秒)。因为这些对不满足您的 WHERE 条件,所以它们未被选中。

于 2013-08-19T23:47:56.380 回答
0

更新的一种方法

SELECT duration / 60 duration
  FROM
(
  SELECT id, imei, timestamp, speed, 
         @d := IF(@s = 0 AND speed > 0, 
                  @d := @d + TIMESTAMPDIFF(SECOND, @t, timestamp),
                  @d) duration, 
         @t := IF(@s = 0 AND speed = 0, @t, timestamp),
         @s := speed 
    FROM stops, (SELECT @d := 0, @s := -1, @t = 0) i
   WHERE imei = 7466
     AND timestamp >= '2013-08-20 00:00:00' AND timestamp <= '2013-08-20 23:59:59' 
   ORDER BY timestamp
 ) z
 ORDER BY timestamp DESC
 LIMIT 1

输出:

+----------+
| 持续时间 |
+----------+
| 4 |
+----------+

这是SQLFiddle演示

于 2013-08-20T00:12:01.707 回答