Oracle выбрать, чтобы найти вхождения пары статусов - PullRequest
0 голосов
/ 27 декабря 2018

У меня есть следующие данные:

STATUS                      DATE                        TIME                        
B                           20181011                    13:28:27                    
B                           20181011                    13:36:05                    
B                           20181011                    15:28:40                    
I                           20181011                    15:28:57                    
I                           20181011                    15:41:56                    
I                           20181018                    08:21:43                    
B                           20181018                    13:38:00                    
I                           20181019                    17:03:00                    
B                           20181023                    09:45:54                    
I                           20181023                    10:35:44                    
I                           20181023                    10:38:11                    

Каждый раз, когда у меня есть последовательность STATUS 'B', я должен использовать последний, то же самое для STATUS 'I', чтобы я мог получить каждую паруэто состояние с учетом приведенного выше правила и расчета времени между ними.Я попытался выбрать несколько вариантов без успеха, но я не смог найти ни одного вопроса, подобного моему.

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

STATUS                      DATE                        TIME                        
B                           20181011                    15:28:40                    
I                           20181018                    08:21:43                    
B                           20181018                    13:38:00                    
I                           20181019                    17:03:00                    
B                           20181023                    09:45:54                    
I                           20181023                    10:38:11                    

Ответы [ 3 ]

0 голосов
/ 27 декабря 2018

Получите сначала все пары времени и даты, соответствующие условию, и присоединитесь к основной таблице:

select tablename.* from (
  select mydate, mytime from tablename t
  where not exists (
    select 1 from tablename 
    where 
      tablename.status = t.status 
      and 
      concat(tablename.mydate, tablename.mytime) = (
        select min(concat(tablename.mydate, tablename.mytime)) from tablename where concat(mydate, mytime) > concat(t.mydate, t.mytime)
      )
  )
) d
inner join tablename
on d.mydate = tablename.mydate and d.mytime = tablename.mytime;

См. demo

0 голосов
/ 27 декабря 2018

Это версия проблемы пробелов и островков.Для этой версии, я думаю, lead() - лучший подход:

select status, date, time
from (select t.*,
             lead(status) over (order by date, time) as next_status
      from t
     ) t
where next_status is null or next_status <> status;
0 голосов
/ 27 декабря 2018

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

Кроме того, я надеюсь , что на самом деле есть один DATE столбец типа данных;в противном случае, если их два (дата и время), вы сохраняете их в столбцах VARCHAR2 (вероятно), что является плохой идеей - я бы предложил вам изменить модель и использовать один столбец типа данных DATE.

Вот так:

SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';

Session altered.

SQL> with test (status, datum) as
  2    (select 'B', to_date('11.10.2018 13:28:27', 'dd.mm.yyyy hh24:mi:ss') from dual union all
  3     select 'B', to_date('11.10.2018 13:36:05', 'dd.mm.yyyy hh24:mi:ss') from dual union all
  4     select 'B', to_date('11.10.2018 15:28:40', 'dd.mm.yyyy hh24:mi:ss') from dual union all
  5     select 'I', to_date('11.10.2018 15:28:57', 'dd.mm.yyyy hh24:mi:ss') from dual union all
  6     select 'I', to_date('11.10.2018 15:41:56', 'dd.mm.yyyy hh24:mi:ss') from dual union all
  7     select 'I', to_date('18.10.2018 08:21:43', 'dd.mm.yyyy hh24:mi:ss') from dual union all
  8     select 'B', to_date('18.10.2018 13:38:00', 'dd.mm.yyyy hh24:mi:ss') from dual union all
  9     select 'I', to_date('19.10.2018 17:03:00', 'dd.mm.yyyy hh24:mi:ss') from dual union all
 10     select 'B', to_date('23.10.2018 09:45:54', 'dd.mm.yyyy hh24:mi:ss') from dual union all
 11     select 'I', to_date('23.10.2018 10:35:44', 'dd.mm.yyyy hh24:mi:ss') from dual union all
 12     select 'I', to_date('23.10.2018 10:38:11', 'dd.mm.yyyy hh24:mi:ss') from dual
 13    ),
 14  inter as
 15    (select status, lag(status) over (order by datum) lag_status, datum
 16     from test
 17    ),
 18  inter_2 as
 19    (select status, datum,
 20       sum(case when status = nvl(lag_status, status) then 0 else 1 end) over (order by datum) grp
 21    from inter
 22    )
 23  select status, max(datum) datum
 24  from inter_2
 25  group by status, grp
 26  order by datum;

S DATUM
- -------------------
B 11.10.2018 15:28:40
I 18.10.2018 08:21:43
B 18.10.2018 13:38:00
I 19.10.2018 17:03:00
B 23.10.2018 09:45:54
I 23.10.2018 10:38:11

6 rows selected.

SQL>
  • INTER CTE выбирает STATUS значение из предыдущей строки
  • INTER_2 создает группы на основеравны ли значения столбца STATUS предыдущей и текущей строки
  • окончательные данные группировок данных по STATUS и GRP (группа) и выбирает значение MAX DATUM
...