MySQL запрос для оценки совокупной продолжительности времени, когда что-то включено - PullRequest
1 голос
/ 10 февраля 2010

У меня есть ряд включенных / выключенных данных времени в таблице, представляющих состояния включения / выключения, или точки, в которых состояние «запускается»

00:00:00    0
04:00:00    1
08:00:00    0
09:00:00    1
15:00:00    0
20:00:00    1
23:59:59    0

Мне нужно рассчитать общую продолжительность (скажем) состояния ВКЛ за 24 часа.

В этом упрощенном примере общая продолжительность = 1 (04: 00: 00-> 08:00:00, 09: 00: 00-> 15:00:00, 20: 00: 00-> 23:59:59 то есть 13:59:59 около 14 ч

Я не могу определить, может ли это быть сделано только в SQL, или должна ли используемая мной базовая структура (django) делать это на основе возвращаемых данных. Очевидно, я бы предпочел, чтобы база данных выполняла тяжелую работу, если это возможно, потому что нам может понадобиться использовать SQL и в нашем отдельном пакете статистики.

Мне не ясно, могу ли я выполнять операции над (скажем) предыдущим или следующим элементом в select, я уверенный пользователь SQL, но не вижу, с чего начать этот или обобщенный подход, есть идеи?

Мне бы очень хотелось, чтобы это было в одном запросе, или каким-то другим умным способом подсчёта этого мне не хватает!

1 Ответ

1 голос
/ 10 февраля 2010

В MySQL нет row_number(), но вы можете выполнить двойное соединение для поиска предыдущей строки:

select 
    sum(case when cur.state = 0 then 0
        else subtime(cur.timeCol, prev.timeCol)
        end) as TotalOnTime
from YourTable cur
join YourTable prev
    on prev.timeCol < cur.timeCol
left join YourTable inbetween
    on prev.timeCol < inbetween.timeCol
    and inbetween.timeCol < cur.timeCol
where inbetween.timeCol is null;

В MySQL вы также можете использовать переменную, которая в этом случае, вероятно, более эффективна:

set @total := '00:00:00';
set @lasttime := '00:00:00';

select 
    @total := addtime(@total, case 
        when state = 0 then 0
        when @lasttime is null then 0
        else subtime(timeCol, @lasttime)
        end)
,   @lasttime := timeCol
from YourTable
order by timeCol;

select 'Result = ', @total;

Код для создания и заполнения тестовой таблицы:

DROP TABLE IF EXISTS YourTable;
CREATE TABLE YourTable (
   timeCol time,
   state bit
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

insert into YourTable values ('00:00:00',    0);
insert into YourTable values ('04:00:00',    1);
insert into YourTable values ('08:00:00',    0);
insert into YourTable values ('09:00:00',    1);
insert into YourTable values ('15:00:00',    0);
insert into YourTable values ('20:00:00',    1);
insert into YourTable values ('23:59:59',    0);
...