oracle-запрос для определения некоторых условий на основе перекрывающихся периодов дат - PullRequest
0 голосов
/ 11 июля 2019

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

, например,

PERSON_ID,RELATION_ID,RELATION_NAME,START_DT,  END_DT, ACTIVE_IND,LATEST_ROW
STEVE     -1          NONE          7/26/2018  10/24/2018 Y          N
STEVE     111         STUDENT       8/8/2018   10/22/2018 Y          N
STEVE     111         STUDENT       10/23/2018 12/31/4712 Y          Y
STEVE     -1          NONE          10/25/2018 2/7/2019   Y          N
STEVE     222         Manager       8/9/2018   12/31/4712 Y          Y
BOB       333         ASSOCIATE     8/9/2018   12/31/4712 Y          Y
BOB       666         TEACHER       8/10/2018  12/31/4712 Y          Y
Dave      555         Director      8/9/2018   12/31/4712 Y          Y

Я хочу найти person_ids с перекрывающимися диапазонами дат, только когда хотя бы один из отношение_данных равен -1.например, BOB является одновременно сотрудником и учителем для перекрывающихся периодов.хорошо иметь 2 роли для человека.Тем не менее, я хочу узнать всех людей с перекрывающимися датами, которые включают в себя отношения «Нет» и какую-то другую роль.Пример: Стив.

Не могли бы вы дать мне несколько советов о том, как придумать запрос

Ответы [ 2 ]

2 голосов
/ 12 июля 2019

Сделал снимок, используя распознавание образов на нем, и он показывает все строки, которые перекрывают друг друга.В этом случае одна строка дважды перекрывается в RELATION_IDs = -1, поэтому она отображает одну и ту же строку в обеих перекрывающихся ситуациях, и запрос помечает ее как overlap_num 1 и 2.

with t (PERSON_ID,RELATION_ID,RELATION_NAME,START_DT,  END_DT, ACTIVE_IND,LATEST_ROW) as (
select 'STEVE',     -1,          'NONE',        to_date('7/26/2018', 'MM/DD/YYYY'), to_date('10/24/2018', 'MM/DD/YYYY'), 'Y', 'N' from dual union all
select 'STEVE',     111,         'STUDENT',      to_date('8/8/2018', 'MM/DD/YYYY'), to_date('10/22/2018', 'MM/DD/YYYY'), 'Y', 'N' from dual union all
select 'STEVE',     111,         'STUDENT',      to_date('10/23/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
select 'STEVE',     -1,          'NONE',         to_date('10/25/2018', 'MM/DD/YYYY'), to_date('2/7/2019', 'MM/DD/YYYY'),   'Y', 'N' from dual union all
select 'STEVE',     222,         'Manager',      to_date('8/9/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
select 'BOB',       333,         'ASSOCIATE',    to_date('8/9/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
select 'BOB',       666,         'TEACHER',      to_date('8/10/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
select 'Dave',      555,         'Director',     to_date('8/9/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual)
select person_id, var_match, overlap_num, relation_id, start_dt, end_dt, start_dt_overlap, end_dt_overlap
  from t
  match_recognize (
  partition by person_id order by start_dt
  measures 
    classifier() as var_match,
    match_number() as overlap_num,
    last(start_dt) as start_dt_overlap,
    first(end_dt) as end_dt_overlap
  all rows per match
  after match skip to last ovlap
  pattern (strt ovlap+)
  define ovlap as (strt.relation_id = -1 and start_dt <= strt.end_dt)
                  or (ovlap.relation_id = -1 and strt.start_dt <= prev(strt.end_dt))
  )
  order by person_id, overlap_num, start_dt;

Пример выполнения:

FSITJA@db01 2019-07-11 14:55:17> with t (PERSON_ID,RELATION_ID,RELATION_NAME,START_DT,  END_DT, ACTIVE_IND,LATEST_ROW) as (
  2  select 'STEVE',     -1,          'NONE',        to_date('7/26/2018', 'MM/DD/YYYY'), to_date('10/24/2018', 'MM/DD/YYYY'), 'Y', 'N' from dual union all
  3  select 'STEVE',     111,         'STUDENT',      to_date('8/8/2018', 'MM/DD/YYYY'), to_date('10/22/2018', 'MM/DD/YYYY'), 'Y', 'N' from dual union all
  4  select 'STEVE',     111,         'STUDENT',      to_date('10/23/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
  5  select 'STEVE',     -1,          'NONE',         to_date('10/25/2018', 'MM/DD/YYYY'), to_date('2/7/2019', 'MM/DD/YYYY'),   'Y', 'N' from dual union all
  6  select 'STEVE',     222,         'Manager',      to_date('8/9/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
  7  select 'BOB',       333,         'ASSOCIATE',    to_date('8/9/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
  8  select 'BOB',       666,         'TEACHER',      to_date('8/10/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual union all
  9  select 'Dave',      555,         'Director',     to_date('8/9/2018', 'MM/DD/YYYY'), to_date('12/31/4712', 'MM/DD/YYYY'), 'Y', 'Y' from dual)
 10  select person_id, var_match, overlap_num, relation_id, start_dt, end_dt, start_dt_overlap, end_dt_overlap
 11    from t
 12    match_recognize (
 13    partition by person_id order by start_dt
 14    measures
 15      classifier() as var_match,
 16      match_number() as overlap_num,
 17      last(start_dt) as start_dt_overlap,
 18      first(end_dt) as end_dt_overlap
 19    all rows per match
 20    after match skip to last ovlap
 21    pattern (strt ovlap+)
 22    define ovlap as (strt.relation_id = -1 and start_dt <= strt.end_dt)
 23                    or (ovlap.relation_id = -1 and strt.start_dt <= prev(strt.end_dt))
 24    )
 25    order by person_id, overlap_num, start_dt;

PERSO VAR_MATCH  OVERLAP_NUM RELATION_ID START_DT            END_DT              START_DT_OVERLAP    END_DT_OVERLAP
----- ---------- ----------- ----------- ------------------- ------------------- ------------------- -------------------
STEVE STRT                 1          -1 2018-07-26 00:00:00 2018-10-24 00:00:00 2018-07-26 00:00:00 2018-10-24 00:00:00
STEVE OVLAP                1         111 2018-08-08 00:00:00 2018-10-22 00:00:00 2018-08-08 00:00:00 2018-10-24 00:00:00
STEVE OVLAP                1         222 2018-08-09 00:00:00 4712-12-31 00:00:00 2018-08-09 00:00:00 2018-10-24 00:00:00
STEVE OVLAP                1         111 2018-10-23 00:00:00 4712-12-31 00:00:00 2018-10-23 00:00:00 2018-10-24 00:00:00
STEVE STRT                 2         111 2018-10-23 00:00:00 4712-12-31 00:00:00 2018-10-23 00:00:00 4712-12-31 00:00:00
STEVE OVLAP                2          -1 2018-10-25 00:00:00 2019-02-07 00:00:00 2018-10-25 00:00:00 4712-12-31 00:00:00

6 rows selected.
1 голос
/ 11 июля 2019

Установка Oracle :

CREATE TABLE table_name ( PERSON_ID, RELATION_ID, RELATION_NAME, START_DT, END_DT, ACTIVE_IND,LATEST_ROW ) AS
SELECT 'STEVE',  -1, 'NONE',      DATE '2018-07-26', DATE '2018-10-24', 'Y', 'N' FROM DUAL UNION ALL
SELECT 'STEVE', 111, 'STUDENT',   DATE '2018-08-08', DATE '2018-10-22', 'Y', 'N' FROM DUAL UNION ALL
SELECT 'STEVE', 111, 'STUDENT',   DATE '2018-10-23', DATE '4712-12-31', 'Y', 'Y' FROM DUAL UNION ALL
SELECT 'STEVE',  -1, 'NONE',      DATE '2018-10-25', DATE '2019-02-07', 'Y', 'N' FROM DUAL UNION ALL
SELECT 'STEVE', 222, 'Manager',   DATE '2018-08-09', DATE '4712-12-31', 'Y', 'Y' FROM DUAL UNION ALL
SELECT 'BOB',   333, 'ASSOCIATE', DATE '2018-08-09', DATE '4712-12-31', 'Y', 'Y' FROM DUAL UNION ALL
SELECT 'BOB',   666, 'TEACHER',   DATE '2018-08-10', DATE '4712-12-31', 'Y', 'Y' FROM DUAL UNION ALL
SELECT 'Dave',  555, 'Director',  DATE '2018-08-09', DATE '4712-12-31', 'Y', 'Y' FROM DUAL;

Запрос

SELECT DISTINCT
       PERSON_ID
FROM   table_name t
WHERE  RELATION_ID = -1
AND    EXISTS (
  SELECT 1
  FROM   table_name o
  WHERE  t.person_id = o.person_id
  AND    t.end_dt    > o.start_dt
  AND    t.start_dt  < o.end_dt
  AND    o.relation_id <> -1
)

Выход

| PERSON_ID |
| :-------- |
| STEVE     |

дБ <> скрипка здесь

...