2013-08-21 3 views
2

У меня есть таблица SQL Server, как это:Top 10 событий длительностью

TimeStamp (datetime)| Alarm (string) | Active (bool) 
01.08.2013 1:30:05 | Alarm 1    | false 
01.08.2013 1:29:54 | Alarm 2    | true 
01.08.2013 1:28:43 | Alarm 1    | true 
01.08.2013 1:27:21 | Alarm 3    | false 
01.08.2013 1:26:35 | Alarm 1    | false 
01.08.2013 1:25:34 | Alarm 1    | true 

я уже отображать верхние вхождений 10 сигнализации:

SELECT TOP 10 Alarm, COUNT(Alarm) AS Occurrence 
FROM MyTable 
WHERE (Active = 'True') 
GROUP BY Alarm 
ORDER BY Occurrence DESC 

теперь нужно времени тревоги топ-10

Цель состоит в том, чтобы иметь сумму продолжительности (от истины до ложной) для каждого отдельного сигнала тревоги.

Я действительно заблокирован этим, я предполагаю, что мне нужно итерировать каждую строку и суммировать значение времени для каждого встречного сигнала.

Но я не знаю, как это сделать с SQL-запросом. Любая помощь или направление будут оценены.

Заранее спасибо


@Roman Пекар: SQL сервер 2008

@ Гордон Линофф: Результат, ожидаемый => верх 10 длительность сигнала тревоги (если тревога верно))

time[min] | Alarm 

50 | Alarm 2 
34 | Alarm 3 
22 | Alarm 1 

... 
+0

Какая версия SQL Server у вас есть? –

+2

Просьба представить образец. Неясно, что вы хотите, чтобы результат был для данных в вопросе. –

+0

И как вы можете рассчитать время для сигналов тревоги 2 и 3, так как есть только одно вхождение каждого (Тревога 2 = 1 истина и Тревога 3 = 1 ложь)? Кроме того, для Тревоги 1 вы хотите 2 строки или только 1. Я имею в виду, вы хотите рассчитать общую продолжительность или продолжительность, 1:25:34 до 1:26:35, а затем 1:28:43 до 1 : 30: 05? –

ответ

1

Вы можете использовать cross apply, чтобы найти первые off после on:

select top 10 active.Alarm 
,  active.TimeStamp as TimeOn 
,  active.TimeStamp as TimeOff 
,  datediff(second, active.TimeStamp, inactive.TimeStamp) as Duration 
from YourTable active 
cross apply 
     (
     select top 1 * 
     from YourTable inactive 
     where inactive.Active = 'false' 
       and inactive.Alarm = active.Alarm 
       and inactive.TimeStamp > active.TimeStamp 
     order by 
       inactive.TimeStamp 
     ) inactive 
where active.Active = 'true' 
order by 
     Duration desc 

See it working at SQL Fiddle.

+0

Спасибо за ваш ответ, это мне очень помогает! – Thierry

1

Вот еще одно решение, которое может быть более эффективным.

;with a as 
(
    select a.Alarm 
    , a.Active 
    , a.[Timestamp] 
    , Sequence = dense_rank() over 
       (
        partition by a.Alarm, a.Active 
        order by a.[TimeStamp] 
       ) 
    from #YourTable a 
), 
b as 
(
    select a.Alarm 
    , Start = b.[Timestamp] 
    , Stop = a.[Timestamp] 
    from a 
    left outer join a b 
    on b.Alarm = a.Alarm 
    and b.Sequence = a.Sequence 
    and b.Active = 'true' 
    where a.Active = 'false' 
) 
select b.Alarm 
, DurationMinutes = sum(datediff(millisecond, b.Start, b.Stop)/1000.0/60.0) 
from b 
group by b.Alarm 
+0

Может быть более эффективным, но также требует более высокой согласованности данных. Если первая строка - это конец предыдущего будильника (запись «выключено»), ваш запрос вернет отрицательную длительность. – Andomar

+0

@Andomar True. Вы можете добавить 'и b.Timestamp