获取持续时间作为重复位置更改的时间戳差异

时间:2015-07-09 07:47:26

标签: mysql

在SQL查询中稍微苦苦挣扎,并希望有助于确定每个人在不断变化的位置的相应持续时间。

一个表格,三列:名称位置时间戳(每两秒新行一次)。

name location timestamp
fred home     2015-07-08 08:02:15
john home     2015-07-08 08:02:16
fred home     2015-07-08 08:02:17
john home     2015-07-08 08:02:18
fred work     2015-07-08 08:07:30
fred work     2015-07-08 08:07:32
fred work     2015-07-08 08:07:34
john work     2015-07-08 08:09:15
john work     2015-07-08 08:09:17
john work     2015-07-08 08:09:19
fred home     2015-07-08 17:17:35
fred home     2015-07-08 17:17:37
john home     2015-07-08 19:10:15
john home     2015-07-08 19:10:17
john home     2015-07-08 19:10:19
john home     2015-07-08 19:10:21

需要确定弗雷德和约翰在家里然后在工作,然后再在家里多久。

不幸的是,尽管如此 TIMEDIFF(min(timestamp), max(timestamp))
确定持续时间,这是一个聚合命令。所以你必须使用group by namegroup by location - 之后它会将时间汇总到一个持续时间值(fred在家中2015-07-08 08:02:15和2015-07-08之间17:17:37),这是不正确的。他实际上在2015-07-08 08:02:15和2015-07-08 08:02:17之间回家,然后又在2015-07-08 17:17之后再次(在工作一段时间后) :35和2015-07-08 17:17:37。

所以我试图让查询显示持续时间(以秒为单位)和<#> 上次见过&#39;:

name location duration last_seen
fred home     2        2015-07-08 08:02:17
fred work     4        2015-07-08 08:07:34
fred home     2        2015-07-08 17:17:37
john home     2        2015-07-08 08:02:18
john work     4        2015-07-08 08:09:19
john home     6        2015-07-08 19:10:21

假设我需要一个查询,该查询根据个人姓名确定持续时间,直到位置名称发生变化(然后重复下一个位置名称更改)。但是,上面使用的时间差总是聚合数据。

1 个答案:

答案 0 :(得分:0)

创建一个名为home_to_work的视图:

CREATE VIEW `home_to_work`AS 
    SELECT b.name, NULL AS `home`, b.timestamp AS `work`
    FROM mytable b
    WHERE b.location = 'work'
            AND NOT EXISTS (
                    SELECT 1 FROM mytable m
                    WHERE b.name = m.name AND m.timestamp < b.timestamp
     )
    UNION ALL
    SELECT a.name, a.timestamp AS `home`, b.timestamp AS `work`
    FROM mytable a
    JOIN mytable b
            ON a.name = b.name AND a.location = 'home' AND b.location = 'work'
     AND a.timestamp < b.timestamp
     AND NOT EXISTS (
                    SELECT 1 FROM mytable m
                    WHERE a.name = m.name AND m.timestamp > a.timestamp AND m.timestamp < b.timestamp
     )
    UNION ALL
    SELECT a.name, a.timestamp AS `home`, NULL AS `work`
    FROM mytable a
    WHERE a.location = 'home'
            AND NOT EXISTS (
                    SELECT 1 FROM mytable m
                    WHERE a.name = m.name AND m.timestamp > a.timestamp
     );

和一个名为work_to_home的视图:

CREATE VIEW `work_to_home`AS 
    SELECT b.name, NULL AS `work`, b.timestamp AS `home`
    FROM mytable b
    WHERE b.location = 'home'
        AND NOT EXISTS (
            SELECT 1 FROM mytable m
            WHERE b.name = m.name AND m.timestamp < b.timestamp
     )
    UNION ALL
    SELECT a.name, a.timestamp AS `work`, b.timestamp AS `home`
    FROM mytable a
    JOIN mytable b
        ON a.name = b.name AND a.location = 'work' AND b.location = 'home'
     AND a.timestamp < b.timestamp
     AND NOT EXISTS (
            SELECT 1 FROM mytable m
            WHERE a.name = m.name AND m.timestamp > a.timestamp AND m.timestamp < b.timestamp
     )
    UNION ALL
    SELECT a.name, a.timestamp AS `work`, NULL AS `home`
    FROM mytable a
    WHERE a.location = 'work'
        AND NOT EXISTS (
            SELECT 1 FROM mytable m
            WHERE a.name = m.name AND m.timestamp > a.timestamp
     );

然后使用此查询:

SELECT `name`, location, `from`, `until`, duration
FROM (
    SELECT h2w.`name`, 'work' AS `location`, h2w.work AS `from`, w2h.work AS `until`, TIMESTAMPDIFF(second, h2w.`work`, w2h.`work`) AS `duration`
    FROM home_to_work h2w
    JOIN work_to_home w2h
      ON h2w.name = w2h.name AND h2w.work < w2h.work AND NOT EXISTS (
        SELECT 1 FROM mytable m
        WHERE h2w.name = m.name AND m.location = 'home' AND m.timestamp > h2w.work AND m.timestamp < w2h.work
    )

    UNION ALL

    SELECT w2h.`name`, 'home' AS `location`, w2h.home AS `from`, h2w.home AS `until`, TIMESTAMPDIFF(second, w2h.`home`, h2w.`home`) AS `duration`
    FROM work_to_home w2h
    JOIN home_to_work h2w
      ON w2h.name = h2w.name AND w2h.home < h2w.home AND NOT EXISTS (
        SELECT 1 FROM mytable m
        WHERE w2h.name = m.name AND m.location = 'work' AND m.timestamp > w2h.home AND m.timestamp < h2w.home
    )
) locations
ORDER BY `name`, `from`

说明:我导出从家到工作的转换,并且工作到home(包括初始null到home / work和final home / work为null)然后在检查它们是连续的时加入这些转换。

这是SQL Fiddle

编辑回复您的评论:

获取给定人员和时间的最后已知位置非常简单:

SELECT location
FROM mytable
WHERE `name` = 'John' AND timestamp < '2015-07-08 11:07:00'
ORDER BY timestamp DESC
LIMIT 1