У меня есть набор данных в SQL, который выглядит следующим образом:

╔═══════════╦═══════╗
║ TimeStamp ║ State ║
╠═══════════╬═══════╣
║  7:10 AM  ║   A   ║
║  7:11 AM  ║   A   ║
║  7:12 AM  ║   A   ║
║  7:13 AM  ║   B   ║
║  7:14 AM  ║   B   ║
║  7:15 AM  ║   A   ║
║  7:16 AM  ║   A   ║
║  7:17 AM  ║   C   ║
║  7:18 AM  ║   C   ║
╚═══════════╩═══════╝

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

╔═══════╦════════════════════╗
║ State ║ Duration (minutes) ║
╠═══════╬════════════════════╣
║   A   ║         2          ║
║   B   ║         1          ║
║   A   ║         1          ║
║   C   ║         1          ║
╚═══════╩════════════════════╝

Может кто-нибудь помочь? Как я могу написать SQL-запрос, который вернет мне эти данные?

Спасибо!

2
Snooks 30 Окт 2015 в 08:05

2 ответа

Лучший ответ

Хорошо, я предполагаю, что нужен MS SQL Server.

Чтобы достичь ожидаемого результата (где C имеет продолжительность 1):

select    
    state, MIN(TimeStamp) StartsAt, EndsAt, datediff(minute,MIN(TimeStamp),EndsAt) DurationMinutes
from (
        select
                t1.state, t1.TimeStamp
                , ISNULL(ca.EndsAt, (select max(timestamp) from table1) ) EndsAt
        from table1 t1
        outer apply (
                  select top (1) t2.timestamp as EndsAt
                  from table1 t2
                  where t1.state <> t2.state and t1.TimeStamp < t2.TimeStamp
                  order by t2.TimeStamp
              ) ca
    ) as derived
group by     
    state, EndsAt

Что касается выборки данных, можно утверждать, что продолжительность C неизвестна, поскольку состояние еще не изменилось. В этом случае это немного проще:

select    
    state, MIN(TimeStamp) StartsAt, EndsAt, datediff(minute,MIN(TimeStamp),EndsAt) DurationMinutes
from (
        select
                t1.state, t1.TimeStamp ,ca.EndsAt
        from table1 t1
        outer apply (
                  select top (1) t2.timestamp as EndsAt
                  from table1 t2
                  where t1.state <> t2.state and t1.TimeStamp < t2.TimeStamp
                  order by t2.TimeStamp
              ) ca
    ) as derived
group by     
    state, EndsAt

http://sqlfiddle.com/#!6/f0dd7e/9

0
Used_By_Already 30 Окт 2015 в 06:26

Вы не упомянули о СУБД, поэтому вот ответ, который подойдет для любой БД. Если вам нужно быстрое решение, укажите, какую базу SQL вы используете, чтобы вы могли использовать определенные функции / команды (доступ к предыдущей, следующей записи, ...), необходимые для такого запроса.

SELECT MIN(timeStamp),MAX(timeStamp),State
FROM(
     SELECT TimeStamp,State,(SELECT count(*) FROM t 
                         where state<>t1.state 
                         and TimeStamp<t1.TimeStamp) as Grp 
                         from t as t1
     ) as t2
GROUP BY State,Grp

демонстрация SQLFiddle

0
valex 30 Окт 2015 в 06:49