SQL, который фильтрует записи, которые соответствуют определенным условиям из данных временных рядов - PullRequest
0 голосов
/ 18 июня 2019

Существует таблица, в которой хранятся данные журнала просмотра видео следующим образом:

|user_id| status |     time         |
-------------------------------------
|user_a |start   |2019-06-18 00:00:00|
|user_a |progress|2019-06-18 00:00:05|
|user_a |progress|2019-06-18 00:00:10|
|user_a |complete|2019-06-18 00:00:15|
|user_a |start   |2019-06-18 00:10:00|
|user_a |complete|2019-06-18 00:10:05|
|user_b |start   |2019-06-18 00:20:00|
|user_b |progress|2019-06-18 00:20:05|
|user_b |progress|2019-06-18 00:20:10|

«start» - это флаг начала просмотра видео, «progress» - флаг просмотра видео, а ««Завершить» - это флаг завершения просмотра видео.

Флаг завершения не всегда устанавливается, поскольку видео может не просматриваться.

Однако в некоторых случаях флаг завершения может быть установлен без прогресса.

Я хочу исключить из приведенных выше записей данных, которые имеют только начало и завершение (без прогресса).

В частности, я хочу исключить следующие записи.

|user_a |start   |2019-06-18 00:10:00|
|user_a |complete|2019-06-18 00:10:05|

Есть ли способ сделать это с помощью sql?

Ответы [ 2 ]

1 голос
/ 18 июня 2019

Вы можете использовать lead() и lag():

select *
from (select t.*,
             lag(status) over (partition by user_id order by time) as prev_status,
             lead(status) over (partition by user_id order by time) as next_status
      from t
     ) t
where not ((status = 'start' and next_status = 'complete') or
           (status = 'complete' and prev_status = 'start')
          );

В качестве альтернативы, учитывая данные образца, вы можете использовать:

where 'progress' in (prev_status, status, next_status);
1 голос
/ 18 июня 2019

Вы можете использовать lead() и lag() оконные аналитические функции:

select user_id, status, time 
  from
  (
   select lag(status,1,'x') over (order by time) lg,
          lead(status,1,'x') over (order by time) ld,
          t.*
     from t
   ) t2
 where not ( lg = ld and status in ('start','complete')) 

Я показал Демо в скрипке для SQL Server DB

...