Как получить час ввода / вывода из одного столбца в Oracle - PullRequest
0 голосов
/ 22 апреля 2020

У меня есть таблица REGISTER в Oracle, которая выглядит следующим образом

| ID | BOOOK_ID |  CLIENT_ID  |   TYPE    |          DATE           |
| 1  |   2447   |   274761    |     1     |    2020-04-07 09:38:54  | 
| 2  |   2447   |   274761    |     2     |    2020-04-07 09:39:25  |
| 3  |   2447   |   274761    |     1     |    2020-04-07 09:39:53  | 
| 4  |   2447   |   274761    |     2     |    2020-04-07 09:41:03  | 
| 5  |   1000   |   274761    |     1     |    2020-04-07 09:52:05  | 
| 6  |   2447   |   274761    |     1     |    2020-04-07 10:04:54  | 
| 7  |   1000   |   274761    |     2     |    2020-04-07 10:05:38  | 
| 8  |   2447   |   274761    |     2     |    2020-04-07 10:06:04  | 
| 9  |   3002   |   274761    |     1     |    2020-04-07 11:22:02  |

И результат, который я хочу получить, выглядит примерно так

| ID | BOOOK_ID |            IN           |          OUT            |
| 1  |   2447   |   2020-04-07 09:38:54   |   2020-04-07 09:39:25   |
| 2  |   2447   |   2020-04-07 09:39:53   |   2020-04-07 09:41:03   |
| 3  |   1000   |   2020-04-07 09:52:05   |   2020-04-07 10:05:38   | 
| 4  |   2447   |   2020-04-07 10:04:54   |   2020-04-07 10:06:04   | 
| 5  |   3002   |   2020-04-07 11:22:02   |                         |

Где type = 1 указывает на дата начала и тип = 2 означает дату окончания.

Ответы [ 2 ]

2 голосов
/ 22 апреля 2020

Вы можете использовать оконные функции. Если мы предположим, что типы правильно чередуются, как в ваших примерах данных:

select rownum as id, book_id, client_id, date as in_date, out_date
from (select t.*,
             lead(date) over (partition by book_id, client_id order by date) as out_date
      from t
     ) t
where type = 1;

Здесь - это db <> скрипта.

Если данные чередуются неправильно Вы должны задать новый вопрос с хорошими примерами того, что может go не так и как вы хотите, чтобы конечный результат выглядел. Это отвечает на вопрос, который вы задали здесь.

0 голосов
/ 22 апреля 2020

MATCH_RECOGNIZE

В Oracle 12.1 и выше вы можете легко сделать это с помощью предложения match_recognize.

alter session set nls_date_format = 'yyyy-mm-dd hh24:mi:ss';

with register (id, book_id, client_id, type_, date_) as (
  select 1, 2447, 274761, 1, to_date('2020-04-07 09:38:54') from dual union all 
  select 2, 2447, 274761, 2, to_date('2020-04-07 09:39:25') from dual union all
  select 3, 2447, 274761, 1, to_date('2020-04-07 09:39:53') from dual union all
  select 4, 2447, 274761, 2, to_date('2020-04-07 09:41:03') from dual union all
  select 5, 1000, 274761, 1, to_date('2020-04-07 09:52:05') from dual union all
  select 6, 2447, 274761, 1, to_date('2020-04-07 10:04:54') from dual union all
  select 7, 1000, 274761, 2, to_date('2020-04-07 10:05:38') from dual union all
  select 8, 2447, 274761, 2, to_date('2020-04-07 10:06:04') from dual union all
  select 9, 3002, 274761, 1, to_date('2020-04-07 11:22:02') from dual
  )
select *
from   register
match_recognize(
  partition by book_id, client_id
  order     by date_
  measures  i.date_ as date_in, o.date_ as date_out
  pattern   ( i o? )
  define    i as type_ = 1, o as type_ = 2
)
order by client_id, date_in, book_id
;

BOOK_ID CLIENT_ID DATE_IN             DATE_OUT
------- --------- ------------------- -------------------
   2447    274761 2020-04-07 09:38:54 2020-04-07 09:39:25
   2447    274761 2020-04-07 09:39:53 2020-04-07 09:41:03
   1000    274761 2020-04-07 09:52:05 2020-04-07 10:05:38
   2447    274761 2020-04-07 10:04:54 2020-04-07 10:06:04
   3002    274761 2020-04-07 11:22:02   

Несколько замечаний: TYPE, DATE, IN являются ключевыми словами Oracle (последние два являются даже зарезервированными ключевыми словами), поэтому они не должны быть именами столбцов ни на входе, ни на выходе. Я изменил первые два на TYPE_ и DATE_ (с завершающим подчеркиванием) и назвал выходные столбцы DATE_IN и DATE_OUT. Кроме того, я изменил имя столбца BOOOK_ID на BOOK_ID, и вы бы поступили так же; в словаре английского языка sh есть только две буквы, а не три.

Затем - если вы попробуете это в SQL Developer, вы обнаружите, что знак вопроса в предложении PATTERN в MATCH_RECOGNIZE выдает ошибку. Это дефект в SQL Developer; если вы выполните тот же запрос в SQL* Plus или других интерфейсах, он будет работать просто отлично. В SQL Developer вам необходимо изменить o? на эквивалентное выражение o{0,1}.

= = = =

PIVOT

В Oracle 11.1 и выше вы можете сделать это с помощью оператора PIVOT. Вам нужна подготовительная работа (подзапрос), чтобы сопоставить события "in" и "out" парам; функция analyti c ROW_NUMBER(), разделенная на книги, клиент и тип , - это простой способ сделать это.

select client_id, book_id, date_in, date_out
from   ( select client_id, book_id, type_, date_, 
                row_number() over (partition by book_id, client_id, type_ 
                                   order by date_) as rn 
         from   register r
       )
pivot  (max(date_) for type_ in (1 as date_in, 2 as date_out))
order  by client_id, book_id, date_in
;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...