Oracle 18 c - Комплекс sql - PullRequest
       7

Oracle 18 c - Комплекс sql

0 голосов
/ 05 марта 2020

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

Emp_ID Number
Emp_flag Varchar2(1)
Date_1 Date
Date_2 Date
create_date Date

Нет PK в этой таблице, есть много записей с дубликатами Emp_id ..

Что мне нужно знать, это когда вводится новый Date_1 (т. е. от нуля до даты или от даты 1 до даты 2) в какую дату это произошло.

Я не могу просто посмотреть на одну запись, чтобы сравнить Date_1 с create_date, потому что есть много раз во множестве записей для данного Emp_ID, когда Date_1 просто «копируется» в новая запись. Date_1, возможно, был изначально введен 15.02.2009 со значением 01.02.2009. Теперь предположим, что Date_2 добавлено 12/12/2020. Таким образом, таблица выглядит следующим образом:

Emp_ID  Emp_flag    Date_1     Date_2      Create_Date
123     Y           Null       Null        1/18/2018
123     Y           02/1/2019  Null        02/15/2019
123     Y           02/1/2019  02/12/2021  02/12/2020

Мне нужен запрос SQL, который сообщит мне, что Emp_ID 123 имеет Date_1 от 01.02.2009, введенное 15.02.2009. и НЕ собирать другие записи.

Ожидаемый результат:

Emp_ID  Emp_flag    Date_1     Date_2      Create_Date
123     Y           02/1/2019  Null        02/15/2019

Пример 2 (уведомление date_1 отличается):

Emp_ID  Emp_flag    Date_1     Date_2      Create_Date
456     Y           Null       Null        1/18/2018
456     Y           10/1/2019  Null        02/15/2019
456     Y           11/2/2019  02/12/2021  02/12/2020

Ожидаемый результат:

Emp_ID  Emp_flag    Date_1     Date_2      Create_Date
456     Y           10/1/2019  Null        02/15/2019
456     Y           11/2/2019  02/12/2021  02/12/2020

Пример 3:

Emp_ID  Emp_flag    Date_1     Date_2      Create_Date
456     Y           Null       Null        1/18/2018
456     Y           10/1/2019  Null        02/15/2019
456     Y           10/1/2019  Null        02/15/2019
456     Y           11/2/2019  02/12/2021  02/12/2020

Ожидаемый результат:

Emp_ID  Emp_flag    Date_1     Date_2      Create_Date
456     Y           10/1/2019  Null        02/15/2019
456     Y           11/2/2019  02/12/2021  02/12/2020

Пример 4:

Emp_ID  Emp_flag    Date_1     Date_2      Create_Date
456     Y           10/1/2019  Null        02/15/2019
456     Y           10/1/2019  Null        02/16/2019

Ожидаемый результат: нет записей.

Ответы [ 3 ]

2 голосов
/ 05 марта 2020

Вы можете использовать функцию Lag, чтобы проверить, существовало или нет предыдущее значение date_1.

SELECT x.emp_id,
       x.date_1,
       x.create_date AS first_date_with_date_1
FROM (
    SELECT t.emp_id,
           t.create_date,
           t.date_1,
           LAG(t.date_1) OVER (PARTITION BY t.emp_id ORDER BY t.create_date) AS last_date_1
    FROM your_table t
) x
WHERE x.date_1 IS NOT NULL
  AND x.last_date_1 IS NULL
1 голос
/ 06 марта 2020

Тест для всех случаев:

with t(emp_id, emp_flag, date_1, date_2, create_date) as (
    select 101, 'Y', null,              null,              date '2018-01-18' from dual union all
    select 101, 'Y', date '2019-02-01', null,              date '2019-02-15' from dual union all
    select 101, 'Y', date '2019-02-01', date '2021-02-12', date '2019-02-16' from dual union all
    select 102, 'Y', null,              null,              date '2018-01-18' from dual union all
    select 102, 'Y', date '2019-02-10', null,              date '2019-02-15' from dual union all
    select 102, 'Y', date '2019-02-11', date '2021-02-12', date '2019-02-16' from dual union all
    select 103, 'Y', null,              null,              date '2018-01-18' from dual union all
    select 103, 'Y', date '2019-02-10', null,              date '2019-02-15' from dual union all
    select 103, 'Y', date '2019-02-10', null,              date '2019-02-15' from dual union all
    select 103, 'Y', date '2019-02-11', date '2021-02-21', date '2020-12-02' from dual )
select emp_id, emp_flag, date_1, date_2, create_date
  from (
    select emp_ID, emp_flag, date_1, date_2, create_date,
           lag(date_1) over (partition by emp_id order by create_date) prev_dt1
      from t )
  where date_1 <> nvl(prev_dt1, date_1 - 1);

Результат:

    EMP_ID EMP_FLAG DATE_1      DATE_2      CREATE_DATE
---------- -------- ----------- ----------- -----------
       101 Y        2019-02-01              2019-02-15
       102 Y        2019-02-10              2019-02-15
       102 Y        2019-02-11  2021-02-12  2019-02-16
       103 Y        2019-02-10              2019-02-15
       103 Y        2019-02-11  2021-02-21  2020-12-02

Редактировать:

при наличии более одной записи с без изменений в Date_1. Он не должен возвращать запись для этого Emp_id

В этом случае date_1 устанавливается в первой строке (id 104). Если вы хотите скрыть строки в таком случае, используйте:

with t(emp_id, emp_flag, date_1, date_2, create_date) as (
    select 104, 'Y', date '2019-02-10', null,              date '2019-02-15' from dual union all
    select 104, 'Y', date '2019-02-10', null,              date '2019-02-16' from dual union all
    select 105, 'Y', date '2019-02-10', null,              date '2019-02-15' from dual union all
    select 105, 'Y', null,              null,              date '2019-02-16' from dual )
select emp_id, emp_flag, date_1, date_2, create_date
  from (
    select emp_ID, emp_flag, date_1, date_2, create_date,
           lag(date_1) over (partition by emp_id order by create_date) prev_dt1, 
           row_number() over (partition by emp_id order by create_date) rn
      from t )
  where (date_1 is not null and prev_dt1 is null and rn > 1)
     or date_1 <> prev_dt1
     or date_1 is null and prev_dt1 is not null;

Я также добавил случай, когда была установлена ​​предыдущая дата, и теперь она равна нулю (id 105). Если это невозможно или вам не нужно, удалите последнюю строку.

0 голосов
/ 05 марта 2020

Здесь вы можете использовать функцию задержки вместо отведения:

with tableA as
(
select 456 as Emp_ID,'Y' as Emp_flag,CAST(NUll as date) as Date_1,CAST(NULL as date) as Date_2,CAST('18Jan2018' as date) as Create_date from dual union
select 456,'Y',CAST('01Oct2019' as date),Null,CAST('15Feb2019' as date) from dual union
select 456,'Y',CAST('02Nov2019' as date),CAST('12Feb2021' as date),CAST('12Feb2020' as date) from dual) 

select x.Emp_ID,x.Emp_flag,x.Date_1,x.Date_2,x.Create_date
from
(select a.*
       ,lag(a.date_1) Over (partition by a.Emp_ID order by a.create_date) as lag_date
from tableA a) x
where x.date_1 is not null and x.date_1<>COALESCE(x.lag_date,CAST('01Jan2100' as date))

Это выдаст значения только при изменении даты_1. Так как сравнения NULL не будут работать, я должен заменить их на 01.01.21. Надеюсь, это поможет.

Редактировать:

Я проверил образец, как вы упомянули, и, похоже, он работает. Если это не работает, пожалуйста, поделитесь ожидаемым и полученным результатом:

with tableA as
(
select 456 as Emp_ID,'Y' as Emp_flag,CAST(NUll as date) as Date_1,CAST(NULL as date) as Date_2,CAST('18Jan2018' as date) as Create_date from dual union
select 456,'Y',CAST('01Oct2019' as date),Null,CAST('15Feb2019' as date) from dual union
select 456,'Y',CAST('01Oct2019' as date),CAST('12Feb2021' as date),CAST('12Feb2020' as date) from dual) 

select x.Emp_ID,x.Emp_flag,x.Date_1,x.Date_2,x.Create_date
from
(select a.*
       ,lag(a.date_1) Over (partition by a.Emp_ID order by a.create_date) as lag_date
from tableA a) x
where x.date_1 is not null and x.date_1<>COALESCE(x.lag_date,CAST('01Jan2100' as date))
...