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