[英]Oracle 18c - Complex sql
我有一个包含以下列的表格:
Emp_ID Number
Emp_flag Varchar2(1)
Date_1 Date
Date_2 Date
create_date Date
这个表上没有PK,有很多记录重复了Emp_id..
我需要知道的是,在发生的日期输入新的Date_1
时(因此 Null 到某个日期,或从 Date 1 到 Date 2)。
我不能只查看单个记录来比较Date_1
和 create_date,因为当Date_1
被简单地“复制”到新记录时,给Emp_ID
Date_1
的许多记录中有很多次。 Date_1
可能是在 02/15/2019 输入的,值为 02/01/2019。 现在假设Date_2
是在Date_2
年 2 月 12 日添加的。 所以表格看起来像这样:
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
的2019年2月1日在2019年2月15日进入和不接任何其他记录。
预期输出:
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
预期输出:无记录。
您可以使用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
测试所有情况:
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)。 如果不可能或您不想要它,则删除最后一行。
您可以在此处使用滞后功能而不是领先:
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))
仅当 date_1 发生变化时才会给出值。 由于 NULL 比较不起作用,我将它们替换为 1/1/2100。 希望这可以帮助。
编辑:
我检查了您提到的样本,它似乎确实有效。 如果它不起作用,请分享您的预期和结果:
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))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.