SQL-запрос определяет время остановки в диапазоне - PullRequest
1 голос
/ 05 июня 2010

Мне нужно определить время остановки транспортного средства, которое отправляет обратно на сервер свои данные о состоянии каждые 30 секунд, и эти данные хранятся в таблице базы данных.

Поля записи о состоянии состоят из (vehicleID, ReceiveDate, ReceiveTime, Speed, Location).

Теперь, что я хочу сделать, это определить каждое время приостановки в момент, когда скорость транспортного средства пришла к нулю, до состояния, в котором транспортное средство снова движется, и так далее для следующего времени приостановки. Например, в определенный день у данного транспортного средства может быть 10 остановленных состояний, и я должен определить продолжительность каждого из них по запросу.
Результат может быть таким:

id Recvdate    Rtime  Duration   
1  2010-05-01  8:30   45min  
1  2110-05-01  12:21  3hour 

1 Ответ

1 голос
/ 19 января 2012

Это приложение для оконных функций (называемых аналитическими функциями в Oracle).

Ваша цель - назначить «номер блока» каждой последовательности остановок. То есть все остановки в последовательности (для транспортного средства) будут иметь одинаковый номер блока, и это будет отличаться от всех других последовательностей остановок.

Вот способ присвоить номер блока:

  1. Создайте флаг скорости, который говорит 1, когда скорость> 0, и 0, когда скорость = 0.
  2. Перечислите все записи, где флаг скорости = 1. Это «блоки».
  3. Выполните самостоятельное объединение, чтобы установить каждый флаг = 0 в блоке (для этого требуется группировка и получение максимального числа блоков).
  4. Суммируйте по продолжительности или как хотите.

Следующий код представляет собой набросок того, что я имею в виду. Это не решит вашу проблему, потому что вы не знаете, как обрабатывать дневные перерывы, какую информацию вы хотите обобщить, и у нее есть ошибка off-by-1 (в каждой последовательности остановок она включает предыдущий безостановочный , если есть).

with vd as 
(
   select vd.*,
      (case when SpeedFlag = 1 
           then ROW_NUMBER() over (partition by id, SpeedFlag) end) as blocknum
   from 
   (
      select vd.*, (case when speed = 0 then 0 else 1 end) as SpeedFlag
      from vehicaldata vd
   ) vd
)
select id, blocknum, COUNT(*) as numrecs, SUM(duration) as duration
from 
(
   select vd.id, vd.rtime, vd.duration, MAX(vdprev.blocknum) as blocknum
   from vd 
   left outer join vd vdprev
     on vd.id = vdprev.id 
     and vd.rtime > vdprev.rtime
   group by vd.id, vd.rtime, vd.duration
) vd
group by id, blocknum
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...