2016-06-08 7 views
0

с помощью SQL Server 2008Выбор записей на основе значения столбца меняется от последней записи

Так у меня есть таблица под названием Штаты и есть данные, как это:

DateTime    | skID | TZ | DomID | EventName | SKGrpID | State 
-------------------------------------------------------------------------- 
2016-06-08 09:22:54.010 | 1234 | 1 | 222 | 0   | 4321 | 0 
2016-06-08 09:22:54.000 | 1234 | 1 | 222 | 3   | 4321 | 3 
2016-06-08 09:21:56.000 | 1234 | 1 | 222 | 8   | 4321 | 4 
2016-06-08 09:19:00.000 | 1234 | 1 | 222 | 7   | 4321 | 4 
2016-06-08 09:18:58.000 | 1234 | 1 | 222 | 4   | 4321 | 4 
2016-06-08 09:13:06.000 | 1234 | 1 | 222 | 6   | 4321 | 6 
2016-06-08 09:10:42.000 | 1234 | 1 | 222 | 4   | 4321 | 4 
2016-06-08 09:10:40.000 | 1234 | 1 | 222 | 1   | 5555 | 1 
2016-06-08 09:00:28.003 | 1234 | 1 | 222 | 1   | 4321 | 1 

Ряды можно рассматривать записи для кого-то, кто отвечает на телефон. Если состояние «4» означает, что они разговаривают по телефону, и если это что-то еще, это не так. Самые старые записи находятся внизу. Итак, третья запись в 9:10:42 - это начало звонка, и запись в 9:13:06 - это конец звонка (состояние изменено с 4 на 6.)

Иногда вызов длится несколько раз Мероприятия. так что запись на 9:18:58 начинается звонок, и она продолжается до записи в 9:21:56 (начало состояний -> 4,4,4,3 < -End)

Я бы хотел: запрос, который каким-то образом выбирает начальную запись и конечную запись, присоединяет их и получает продолжительность. Проблема в том, что я понятия не имею, как я могу выбрать, основываясь на изменении состояния от 4 до чего-то другого. Я также пытаюсь выяснить, как выбрать каждый из старта каждого вызова (начальные записи будут представлять собой запись с состоянием 4, а предыдущая запись - что-то другое (так, например, государства 1, 4, 3, 6, 4 , 5 будет второй и 5-й записи будет начинается вызов и 3 и 6 будет концы вызовов.))

идеальный результат будет что-то вроде

StartTime, EndTime, Duration, skID, TZ, DomID, SKGrpID, StartEvent, StartState, EndEvent, EndState 

Я могу сделать это в настоящее время на python, просто запрашивая все строки, а затем создавая dicts и сопоставляя вызовы таким образом, но я хотел бы сделать как можно больше в SQL. Является ли такой выбор даже возможным?

+0

Это возможно. Но при переполнении стека вы должны показать, что вы пробовали. Но чтобы дать вам подсказку: посмотрите LIMIT 1 и ORDER BY ASC/DESC. Удачи. – user3741598

+0

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

+0

@ user3741598 Реализовано, что я поставил неправильный тег. Это sql-сервер, поэтому я даже не могу использовать ограничение. – user5999614

ответ

0
SELECT 'StartTime' 
    , 'EndTime' 
    , 'Duration' 
    , 'skID' 
    , 'TZ' 
    , 'DomID' 
    , 'SKGrpID' 
    , 'StartEvent' 
    , 'StartState' 
    , 'EndEvent' 
    , 'EndState'; 

Если это не то, что вы имели в виду, уточните пожалуйста. ;-)

+1

У меня даже нет слов. – user5999614

1

Это один из способов сделать это:

select 
    max(case when RN = 1 then DateTime end) as StartTime, 
    max(case when RN = 2 then DateTime end) as EndTime, 
    max(case when RN = 1 then EventName end) as StartEvent, 
    max(case when RN = 2 then EventName end) as EndEvent 
from 
(
    select 
    *, 
    row_number() over (partition by CallId order by DateTime) as RN 
    from 
    (
    select 
     *, 
     sum(CallStatus) over (order by DateTime) as CallId 
    from 
    (
     select 
     * 
     from 
     (
     select 
      *, 
      lag(CallStatus) over (order by DateTime) as PrevCallStatus 
     from 
     (
      select 
      DateTime, 
      State, 
      EventName, 
      case when State = 4 then 1 else 0 end as CallStatus 
      from #Table1 
     ) A 
    ) B 
     where CallStatus != PrevCallStatus 
    ) C 
) D 
) E 
group by CallId 

Это начинается с сокровенным производной таблицей A, которая используется для присвоения статуса вызова 1/0. Таблица B используется для получения предыдущего значения CallStatus, которое затем используется для фильтрации строк, имеющих тот же CallStatus. Поскольку CallStatus равен 1/0, его можно использовать в общей сумме для вычисления отдельного идентификатора для каждого вызова. Поскольку данные из этого всегда будут содержать 2 строки, row_number используется для присвоения строк числу (1 = start, 2 = end), и тогда это используется в окончательном выборе, чтобы получить данные отдельно от начальных и конечных строк.

Это не все поля, но, по крайней мере, это должно вам начать :)

Это предполагает, что вы всегда имеют окончание записи для звонков, и работает только в SQL Server 2012 или более поздней версии. Для более старых версий вам нужно будет создать что-то более сложное для общего количества и отставания. Скорее всего, лучшим вариантом будет именно курсор.

+0

Спасибо вам большое спасибо! Это, к сожалению, SQL Server 2008 версии 10.5, поэтому мне нужно найти какой-то способ не иметь функции задержки, но это, по крайней мере, дало мне представление о том, как это сделать, поэтому еще раз спасибо. – user5999614

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