我有一个记录实体的每个状态变化的表
id recordTime Status
ID1 2014-03-01 11:33:00 Disconnected
ID1 2014-03-01 12:13:00 Connected
ID2 2014-03-01 12:21:00 Connected
ID1 2014-03-01 12:24:00 Disconnected
ID1 2014-03-01 12:29:00 Connected
ID2 2014-03-01 12:40:00 Disconnected
ID2 2014-03-01 13:03:00 Connected
ID2 2014-03-01 13:13:00 Disconnected
ID2 2014-03-01 13:29:00 Connected
ID1 2014-03-01 13:30:00 Disconnected
我需要计算总的非活动时间,即给定时间窗口内每个ID的“已连接”和“最后断开”状态之间的时间。
对于上表和时间范围2014-03-01 11:00:00至2014-03-01 14:00:00输出应为:
ID InactiveTime
ID1 01:15:00
ID2 02:00:00
答案 0 :(得分:1)
这就是我理解您的问题SQL Fiddle
的方法select id, sum(diff) as inactive
from (
select
recordtime,
recordTime -
lag(recordTime, 1, recordTime)
over(
partition by id
order by recordTime
)
as diff,
status,
id
from t
) s
where status = 'Connected'
group by id
order by id
;
id | inactive
----+----------
1 | 00:45:00
2 | 00:39:00
你能解释一下你想要的输出吗?
答案 1 :(得分:1)
特殊的困难是不要错过超出时间范围的时间
假设任何给定id
的下一行总是具有相反的状态
使用列名ts
代替recordTime
:
WITH span AS (
SELECT '2014-03-01 13:00'::timestamp AS s_from -- start of time range
, '2014-03-01 14:00'::timestamp AS s_to -- end of time range
)
, cte AS (
SELECT id, ts, status, s_to
, lead(ts, 1, s_from) OVER w AS span_start
, first_value(ts) OVER w AS last_ts
FROM span s
JOIN tbl t ON t.ts BETWEEN s.s_from AND s.s_to
WINDOW w AS (PARTITION BY id ORDER BY ts DESC)
)
SELECT id, sum(time_disconnected)::text AS total_disconnected
FROM (
SELECT id, ts - span_start AS time_disconnected
FROM cte
WHERE status = 'Connected'
UNION ALL
SELECT id, s_to - ts
FROM cte
WHERE status = 'Disconnected'
AND ts = last_ts
) sub
GROUP BY 1
ORDER BY 1;
按要求返回间隔 在所选时间范围内没有条目的ID不会显示。你必须另外查询它们。
SQL Fiddle.
注意:我将结果total_disconnected
投射到小提琴中text
,因为类型interval
以可怕的格式显示。
评论中的每个请求。
添加到上面的查询(在最终ORDER BY 1
之前):
...
UNION ALL
SELECT id, total_disconnected
FROM (
SELECT DISTINCT ON (id)
t.id, t.status, (s.s_to - s.s_from)::text AS total_disconnected
FROM span s
JOIN tbl t ON t.ts < s.s_from -- only from before time range
LEFT JOIN cte c USING (id)
WHERE c.id IS NULL -- not represented in selected time frame
ORDER BY t.id, t.ts DESC -- only the latest entry
) sub
WHERE status = 'Disconnected' -- only if disconnected
ORDER BY 1;
现在,只有在或所选时间范围内没有参赛作品的ID才会显示。
答案 2 :(得分:0)
select id , sum(diff) inactif_time
from
(
SELECT id, "recordTime", "Status" ,LEAD("recordTime") OVER(PARTITION BY id order by "recordTime" ),LEAD("recordTime") OVER(PARTITION BY id order by "recordTime" ) - "recordTime" diff
FROM my_table
) B
where "Status" = 'Disconnected'
group by id
但它输出:
"ID1";"00:45:00"
"ID2";"00:39:00"