oracle sql для извлечения дат наблюдения за предыдущей датой - PullRequest
0 голосов
/ 29 июня 2018
CREATE TABLE tst_tbl
(
   id                 NUMBER,
   last_name          VARCHAR2 (50),
   first_name         VARCHAR2 (50),
   dob                DATE,
   register_dt        DATE,
   register_loc       VARCHAR2 (50),
   visit_dt           DATE,
   visit_loc          VARCHAR2 (50),
   visit_comments   VARCHAR2 (30)
);


INSERT INTO tst_tbl VALUES(1234, 'John', 'Smith', to_date('12/01/1980','MM/DD/YYYY') , to_date('09/05/2017' ,'MM/DD/YYYY')   ,'NEW YORK',  to_date('02/26/2018','MM/DD/YYYY'), 'NEW JERSEY', '');
INSERT INTO tst_tbl VALUES(1234, 'John', 'Smith', to_date('12/01/1980','MM/DD/YYYY') , to_date('09/05/2017' ,'MM/DD/YYYY')   ,'NEW YORK',  to_date('2/12/2018', 'MM/DD/YYYY'),'NEW JERSEY', '');
INSERT INTO tst_tbl VALUES(1234, 'John', 'Smith', to_date('12/01/1980','MM/DD/YYYY') , to_date('09/05/2017' ,'MM/DD/YYYY')   ,'NEW YORK',  to_date('11/6/2017', 'MM/DD/YYYY'),'NEW JERSEY', '');
INSERT INTO tst_tbl VALUES(1234, 'John', 'Smith', to_date('12/01/1980','MM/DD/YYYY') , to_date('09/05/2017' ,'MM/DD/YYYY')   ,'NEW YORK',  to_date('10/23/2017','MM/DD/YYYY'), 'NEW JERSEY', '');
INSERT INTO tst_tbl VALUES(1234, 'John', 'Smith', to_date('12/01/1980','MM/DD/YYYY') , to_date('09/05/2017' ,'MM/DD/YYYY')   ,'NEW YORK',  to_date('3/27/2018', 'MM/DD/YYYY'),'NEW JERSEY', '');
INSERT INTO tst_tbl VALUES(1234, 'John', 'Smith', to_date('12/01/1980','MM/DD/YYYY') , to_date('09/05/2017' ,'MM/DD/YYYY')   ,'NEW YORK',  to_date('3/19/2018', 'MM/DD/YYYY'),'NEW JERSEY', '');
INSERT INTO tst_tbl VALUES(1234, 'John', 'Smith', to_date('12/01/1980','MM/DD/YYYY') , to_date('09/05/2017' ,'MM/DD/YYYY')   ,'NEW YORK',  to_date('9/11/2017', 'MM/DD/YYYY'),'NEW JERSEY', '');
INSERT INTO tst_tbl VALUES(1234, 'John', 'Smith', to_date('12/01/1980','MM/DD/YYYY') , to_date('2/7/2018'   ,'MM/DD/YYYY')   ,  'NEW YORK',to_date('11/6/2017 ','MM/DD/YYYY'), 'NEW JERSEY', '');
INSERT INTO tst_tbl VALUES(1234, 'John', 'Smith', to_date('12/01/1980','MM/DD/YYYY') , to_date('2/7/2018'   ,'MM/DD/YYYY')   ,  'NEW YORK',to_date('3/19/2018', 'MM/DD/YYYY'),'NEW JERSEY', '');
INSERT INTO tst_tbl VALUES(1234, 'John', 'Smith', to_date('12/01/1980','MM/DD/YYYY') , to_date('2/7/2018'   ,'MM/DD/YYYY')   ,  'NEW YORK',to_date('9/11/2017', 'MM/DD/YYYY'),'NEW JERSEY', '');
INSERT INTO tst_tbl VALUES(1234, 'John', 'Smith', to_date('12/01/1980','MM/DD/YYYY') , to_date('2/7/2018'   ,'MM/DD/YYYY')   ,  'NEW YORK',to_date('3/27/2018', 'MM/DD/YYYY'),'NEW JERSEY', '');
INSERT INTO tst_tbl VALUES(1234, 'John', 'Smith', to_date('12/01/1980','MM/DD/YYYY') , to_date('2/7/2018'   ,'MM/DD/YYYY')   ,  'NEW YORK',to_date('2/26/2018', 'MM/DD/YYYY'),'NEW JERSEY', '');
INSERT INTO tst_tbl VALUES(1234, 'John', 'Smith', to_date('12/01/1980','MM/DD/YYYY') , to_date('2/7/2018'   ,'MM/DD/YYYY')   ,  'NEW YORK',to_date('10/23/2017','MM/DD/YYYY'), 'NEW JERSEY', '');
INSERT INTO tst_tbl VALUES(1234, 'John', 'Smith', to_date('12/01/1980','MM/DD/YYYY') , to_date('2/7/2018'   ,'MM/DD/YYYY')   ,  'NEW YORK',to_date('2/12/2018', 'MM/DD/YYYY'),'NEW JERSEY', '');
COMMIT;

Я хочу получить информацию о немедленном посещении (visit_dt, visit_loc, ..) после даты регистрации.

например:

1234, John, Smith, 12/01/1980, 09/05/2017,  NEW YORK, 9/11/2017, NEW JERSEY
1234, John, Smith, 12/01/1980, 2/7/2018,  NEW YORK, 2/12/2018, NEW JERSEY

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

 SELECT 
      dt, vst_type, register_dt, vst_dt
    FROM 
    (
      SELECT 
        id, dt, vst_type, 
        dt AS register_dt,
        ROW_NUMBER () OVER 
            ( 
              PARTITION BY id, dt ORDER BY
                CASE 
                  WHEN vst_type = 'REGISTER_DT' THEN 1 ELSE 2 END
            )
        AS vst_dt_rnum,
        LEAD(dt) OVER (PARTITION BY id ORDER BY dt) AS vst_dt
      FROM 
      (
        SELECT id, register_dt AS dt, 'REGISTER_DT' vst_type FROM tst_tbl
        UNION
        SELECT id, visit_dt AS dt, 'VISIT_DT' vst_type FROM tst_tbl
      )
    )
    WHERE vst_dt_rnum = 1 AND vst_type = 'REGISTER_DT'

Ответы [ 3 ]

0 голосов
/ 30 июня 2018

Если я правильно понимаю, и если предположить, что идентификатор является уникальным идентификатором, вы хотите сгруппировать строки по (ID, REGISTER_DT) и по каждой группе, чтобы сохранить только строки с VISIT_DT> = REGISTER_DT, а затем из каждой группы выберите самую раннюю (самую старую) строку с помощью VISIT_DT. Если так, что-то вроде этого должно работать:

select (columns you want)
from   (
         select t.* 
              , row_number() over (partition by id, register_dt
                                   order by visit_dt) as rn
         from   tst_tbl t
         where  visit_dt >= register_dt
       )
where  rn = 1
;
0 голосов
/ 30 июня 2018

Попробуйте это

Select id, last_name, first_name, dob, register_dt, register_loc,
visit_dt
From (
  Select r.id, r.last_name, r.first_name, r.dob, r.register_dt, r.register_loc,
r.visit_dt, r.visit_loc, row_number() over (partition by r.register_dt order by r.visit_dt) r
From tst_tbl r
where register_dt < visit_dt
) x
Where x.r = 1
0 голосов
/ 29 июня 2018

Я чувствую, что вы слишком усложняете вещи. Вот способ, которым вы можете добавить индикатор, если дата посещения следует за датой регистрации <30 дней. Если по какой-то причине это не работает, отредактируйте вопрос и добавьте дополнительные данные (например, как должен выглядеть результат?) </p>

select r.*, 
    case when (floor(visit_dt - register_dt) between 0 and 29) 
         then 'Y' else 'N' 
         end as less_than_30_days
from tst_tbl r;

Но это зависит от вашего примера вывода. На основании вашего запроса создается впечатление, что вы пытаетесь найти все посещения, у которых любая дата регистрации за последние 30 дней (для этого идентификатора). Если вы предпочитаете это, вот более простой способ сделать это.

select v.*,
    (select nvl(max('Y'),'N')
      from tst_tbl r
      where r.id = v.id
        and (floor(v.visit_dt - r.register_dt) between 0 and 29))
      as reg_within_30_days
from tst_tbl v;
...