Объединение последовательных записей в TSQL - PullRequest
0 голосов
/ 29 января 2011

У меня есть база данных сообщений, которые содержат различную информацию, которая поступает. Одна такая часть - это сообщения об изменении состояния, поэтому моя таблица выглядит следующим образом.

    +-----------+--------------+---------+
    | MessageId | RecievedUTC  |  State  |
    +-----------+--------------+---------+
    |    1      | 1/1/2010 5pm |   Off   |
    +-----------+--------------+---------+
    |    2      | 1/2/2010 8am |   Idle  |
    +-----------+--------------+---------+
    |    3      | 1/2/2010 9am | Working |
    +-----------+--------------+---------+

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

    +---------+---------------+--------------+
    |  State  |    StartUTC   |    StopUTC   |
    +---------+---------------+--------------+
    |   Off   | 1/1/2010 5pm  | 1/2/2010 8am |
    +---------+---------------+--------------+
    |   Idle  | 1/1/2010 8am  | 1/2/2010 9am |
    +---------+---------------+--------------+

и т.д.. На мой взгляд, это не сложнее, чем объединение таблицы с самим собой, смещение на 1 запись по заказу RecieveUTC.

Лучший TSQL, который я мог придумать, это что-то вроде

SELECT m1.State, m1.RecievedUTC as StartUTC, MIN(m2.RecievedUTC) as StopUTC
FROM MessageStates as m1
  INNER JOIN MessageStates as m2 ON MessageStates ON m2.RecievedUTC > m1.RecievedUTC
GROUP BY m1.MessageId, m1.State, m1.RecievedUTC

Или как подзапрос, чтобы получить StopUTC, но оба работают ужасно, только 30-40 тыс. Записей занимают почти 5 минут, чтобы выполнить это объединение.

Если бы я написал это на C #, я бы следил за предыдущим RecceiveUTC и указывал состояние, чтобы, когда я увидел следующую запись, я мог объединить с ней следующую RecceiveUTC и в линейном времени получить данные так, как хотел.

1 Ответ

2 голосов
/ 29 января 2011

Попробуйте это:

WITH MsgStates AS 
(
  SELECT a.*, ROW_NUMBER() OVER(ORDER BY RecievedUTC ) RN
    FROM MessageStates a
)
SELECT a.State, a.RecievedUTC StartUTC, b.RecievedUTC StartUTC
  FROM MsgStates a, MsgStates b
 WHERE a.rn = b.rn+1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...