【问题标题】:oracle sql to retrieve followup dates from a preceding dateoracle sql从前一个日期检索后续日期
【发布时间】:2018-06-29 19:18:03
【问题描述】:
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'

【问题讨论】:

    标签: oracle lead


    【解决方案1】:

    如果我理解正确,并假设 ID 是唯一标识符,您希望按 (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
    ;
    

    【讨论】:

    • 感谢一百万 mathguy,这就是我要找的。再次感谢
    【解决方案2】:

    我觉得你把事情复杂化了。如果访问日期比注册日期晚

    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 天内具有 any 注册日期的所有访问(针对该 ID)。如果您更愿意这样做,这里有一种更简单的方法。

    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;
    

    【讨论】:

    • 感谢您的回复 kfinity,我已经编辑了我的问题。
    【解决方案3】:

    试试这个

    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
    

    【讨论】:

      猜你喜欢
      • 2014-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-14
      • 2021-08-19
      • 2016-04-05
      相关资源
      最近更新 更多