记录之间流逝的平均时间
Mean time that lapsed between records
我有 table 个汽车 ID - id
及其电池电量 - battery
,每十分钟收集一次。
我的目标是以下输出:电池从 100 下降到 0 所需的平均时间。我的 objective 是对所有汽车 ID 取全局平均值,即平均时间所有唯一 ID 的 battery = 100
和 battery = 0
之间的区别。一个小警告是 0 必须在 100 之后,换句话说,我想排除充电时间(当 100 在 0 之后)。
如何在 psql
中编写这样的查询?
这是一辆车的数据示例:
id| time| battery
54 | 2017-12-12 09:50:04.402775+00 | 100
54 | 2017-12-12 09:40:04.618926+00 | 100
54 | 2017-12-12 09:30:04.11399+00 | 100
54 | 2017-12-12 09:20:03.906716+00 | 100
54 | 2017-12-12 09:10:03.955133+00 | 100
54 | 2017-12-12 09:00:04.678508+00 | 100
54 | 2017-12-12 08:50:03.733471+00 | 100
54 | 2017-12-12 08:40:03.65688+00 | 100
54 | 2017-12-12 08:30:04.260608+00 | 100
54 | 2017-12-12 08:20:03.98387+00 | 100
54 | 2017-12-12 08:10:04.164129+00 | 98
54 | 2017-12-12 08:00:04.597976+00 | 98
54 | 2017-12-12 07:50:04.501231+00 | 98
54 | 2017-12-12 07:40:04.441531+00 | 98
54 | 2017-12-12 07:30:04.310876+00 | 98
54 | 2017-12-12 07:20:04.317241+00 | 98
54 | 2017-12-12 07:10:03.856432+00 | 67
54 | 2017-12-12 07:00:03.628862+00 | 67
54 | 2017-12-12 06:50:03.868495+00 | 67
54 | 2017-12-12 06:40:04.490324+00 | 67
54 | 2017-12-12 06:30:03.83739+00 | 67
54 | 2017-12-12 06:20:03.817014+00 | 67
54 | 2017-12-12 06:10:04.081174+00 | 29
54 | 2017-12-12 06:00:04.178765+00 | 29
data_type
--------------------------
integer
timestamp with time zone
integer
因此,您只需要在下一个 100 之前有一个 0 的 100。
select avg(extract(epoch from (next_time - time) ) as avg_recharge_time
from (select t.*,
lead(battery) over (partition by id order by time) as next_battery,
lead(time) over (partition by id order by time) as next_time
from t
where battery in (0, 100)
) t
where battery = 100 and next_battery = 0;
这回答了您提出的问题。然而。我可以想象你的情况更复杂。例如,如果电池可以部分充电,那么这将给出不正确的结果。如果您遇到这种情况,请提出 另一个 问题,并提供适当的示例数据和解释。
我有 table 个汽车 ID - id
及其电池电量 - battery
,每十分钟收集一次。
我的目标是以下输出:电池从 100 下降到 0 所需的平均时间。我的 objective 是对所有汽车 ID 取全局平均值,即平均时间所有唯一 ID 的 battery = 100
和 battery = 0
之间的区别。一个小警告是 0 必须在 100 之后,换句话说,我想排除充电时间(当 100 在 0 之后)。
如何在 psql
中编写这样的查询?
这是一辆车的数据示例:
id| time| battery
54 | 2017-12-12 09:50:04.402775+00 | 100
54 | 2017-12-12 09:40:04.618926+00 | 100
54 | 2017-12-12 09:30:04.11399+00 | 100
54 | 2017-12-12 09:20:03.906716+00 | 100
54 | 2017-12-12 09:10:03.955133+00 | 100
54 | 2017-12-12 09:00:04.678508+00 | 100
54 | 2017-12-12 08:50:03.733471+00 | 100
54 | 2017-12-12 08:40:03.65688+00 | 100
54 | 2017-12-12 08:30:04.260608+00 | 100
54 | 2017-12-12 08:20:03.98387+00 | 100
54 | 2017-12-12 08:10:04.164129+00 | 98
54 | 2017-12-12 08:00:04.597976+00 | 98
54 | 2017-12-12 07:50:04.501231+00 | 98
54 | 2017-12-12 07:40:04.441531+00 | 98
54 | 2017-12-12 07:30:04.310876+00 | 98
54 | 2017-12-12 07:20:04.317241+00 | 98
54 | 2017-12-12 07:10:03.856432+00 | 67
54 | 2017-12-12 07:00:03.628862+00 | 67
54 | 2017-12-12 06:50:03.868495+00 | 67
54 | 2017-12-12 06:40:04.490324+00 | 67
54 | 2017-12-12 06:30:03.83739+00 | 67
54 | 2017-12-12 06:20:03.817014+00 | 67
54 | 2017-12-12 06:10:04.081174+00 | 29
54 | 2017-12-12 06:00:04.178765+00 | 29
data_type
--------------------------
integer
timestamp with time zone
integer
因此,您只需要在下一个 100 之前有一个 0 的 100。
select avg(extract(epoch from (next_time - time) ) as avg_recharge_time
from (select t.*,
lead(battery) over (partition by id order by time) as next_battery,
lead(time) over (partition by id order by time) as next_time
from t
where battery in (0, 100)
) t
where battery = 100 and next_battery = 0;
这回答了您提出的问题。然而。我可以想象你的情况更复杂。例如,如果电池可以部分充电,那么这将给出不正确的结果。如果您遇到这种情况,请提出 另一个 问题,并提供适当的示例数据和解释。