2013-04-25 1 views
2

Использование SQL Server 2008+ Не уверен, как задать вопрос, так вот некоторые примерные данные:SQL группе включения/выключения (бит) вместе, чтобы вычислить длительность

case_id start_time   timer_name type value duration 
8386 2013-02-01 19:25:52 Patient In 25  1  NULL 
8386 2013-02-01 20:18:31 Patient Out 25  0  NULL 
8386 2013-02-01 20:13:13 Anes. Start 26  1  NULL 
8386 2013-02-01 20:18:37 Anes. Stop 26  0  NULL 
8386 2013-02-01 20:13:25 Induction 27  1  NULL 
8386 2013-02-01 20:18:41 Emergence 27  0  NULL 
8386 2013-02-01 20:13:31 Incision 28  1  NULL 
8386 2013-02-01 20:18:45 Closing  28  0  NULL 
8451 2013-02-06 18:37:44 Anesthesia 1  1  NULL 
8451 2013-02-06 18:37:48 Incision 1  1  NULL 
8451 2013-02-06 18:05:32 Patient In 25  1  NULL 
8451 2013-02-06 18:07:41 Anes. Start 26  1  NULL 
8451 2013-02-06 18:11:00 Induction 27  1  NULL 
8451 2013-02-06 18:11:54 Emergence 27  0  NULL 
8451 2013-02-06 18:11:20 Incision 28  1  NULL 

Вот это SQL я использую чтобы создать этот список:

SELECT  case_id, start_time, timer_name, type, value, duration 
FROM   dbo.event AS ev WITH (nolock) 
WHERE   (type IN (1, 2, 3, 25, 26, 27, 28)) AND (defunct = 'N') 
ORDER BY  case_id, type, start_time 

Что мне нужно сделать, это группа типов вместе, заказанные case_id, типа, и start_time, а затем рассчитать длительность между первой записью с 1 значением и следующий один с значение 0 того же типа. В приведенных выше данных, случай 8386 должен иметь следующие данные:

8386 2013-02-01 19:25:52 Patient In 25  1  52:39 
8386 2013-02-01 20:13:13 Anes. Start 26  1  5:24 
8386 2013-02-01 20:13:25 Induction 27  1  5:16 
8386 2013-02-01 20:13:31 Incision 28  1  5:14 

Надеюсь, я сделал математику правильно. Продолжительность не должна быть в этом формате. Я ожидаю, что количество секунд лучше, но этот формат легче читать в вопросе. Также не имеет значения, какое имя отображается в поле timer_name.

Поймите, что я могу получить несколько 1 значений для типа в строке или нескольких 0 значений в строке. Мне нужно связать первый 1 с первым 0 и вычислить эту продолжительность, а затем искать следующий 1 и т. Д. Это означает, что в каждом случае может быть несколько групп для каждого типа. Если для значения 1 нет значения 0, я буду использовать case_end_time, который я могу извлечь из другой таблицы.

+0

Является ли это SQLServer или другой СУБД? –

+0

Использование SQL Server 2008. Добавлено также и на вопрос. Благодаря! – mdutra

ответ

1

Эта версия запроса использует коррелированный подзапрос, чтобы найти следующее время запуска в соответствии с вашей логикой. В SQL Server 2012, это использовать бы функцию lead(), но нет в наличии:

select case_id, start_time, timer_name, type, value, duration, 
     (select top 1 start_time 
     from event e2 
     where e2.case_id = e.case_id and e2.type = e.type and e2.value = 0 and 
       e2.start_time > e.start_time 
     order by start_time desc 
     ) - start_time as duration 
from event e 
WHERE (type IN (1, 2, 3, 25, 26, 27, 28)) AND (defunct = 'N') and value = 1 

Ваш пример не имеет несколько «0». Если вы хотите, только первый, мы можем найти его с помощью row_number():

select case_id, start_time, timer_name, type, value, duration, 
     (next_start_time - start_time) as duration 
from (select case_id, start_time, timer_name, type, value, duration, 
      (select top 1 start_time 
       from event e2 
       where e2.case_id = e.case_id and e2.type = e.type and e2.value = 0 and 
        e2.start_time > e.start_time 
       order by start_time desc 
      ) as next_start_time, 
      ROW_NUMBER() over (partition by case_id, type order by start_time) as seqnum 
     from event e 
     WHERE (type IN (1, 2, 3, 25, 26, 27, 28)) AND (defunct = 'N') and value = 1 
    ) t 
where seqnum = 1 
+0

Я все еще смотрю на это, так как это выглядит как правильное направление, но работает, так как SQL всегда возвращает next_start_time/duration как null. не является ли предложение where значения = 0 фильтровать все 1 так, чтобы «select top 1 ... e2.value = 1 ...» никогда ничего не вернет? – mdutra

+0

@mdutra. , , Я перевернул значения 0 и 1. Я только что исправил это. –

+0

Спасибо, что сделал трюк! – mdutra

0

Хорошо, вы должны использовать кучу вещей, во-первых, чтобы получить первую 1 и 0 вы должны использовать функцию row_number разделенную по значению, таким образом вы не можете использовать предложение where для фильтрации по строке = 1. На этом этапе у вас будет первое из 1 из 0 каждого случая. Если вы делаете это в разделенных запросах, вы можете присоединиться к ним и сделать разницу между двумя датами. Некоторые вещи, как это:

SELECT 
     case_id, type, DATEDIFF(mm, a.start_time, b.start_time) duration 
    FROM 
     (SELECT  case_id, start_time, timer_name, type, value, duration 
     FROM   dbo.event AS ev WITH (nolock) 
     WHERE  (type IN (1, 2, 3, 25, 26, 27, 28)) AND (defunct = 'N') 
      AND ROW_NUMBER() OVER(PARTITION BY type, value ORDER BY case_id, type) = 1 --Get the first row only 
      AND TYPE = 0 -- And the ones of type 0 
     ) a INNER JOIN 
     (SELECT  case_id, start_time, timer_name, type, value, duration 
     FROM   dbo.event AS ev WITH (nolock) 
     WHERE  (type IN (1, 2, 3, 25, 26, 27, 28)) AND (defunct = 'N') 
      AND ROW_NUMBER() OVER(PARTITION BY type, value ORDER BY case_id, type) = 1 --Get the first row only 
      AND TYPE = 1 -- And the ones of type 1   
     ) b 
    ON 
    a.case_id = b.case_id AND 
    a.[type] = b.[type] 

Я не проверял, но это идея

Смежные вопросы