比较特定位置的两个日期之间的日期
Compare dates between two dates at specific positions
给定 table 中的以下示例记录:MY_DATES,使用 Oracle SQL and/or PL/SQL,我需要一直拿这个table中的第一个DATE_REGISTERED,即26/10/2019,然后前进到第三个DATE_REGISTEREDrecord/value,即2/02/ 2020 并检查它们之间的差异是否大于 13 周,即
select to_date('2/02/2020','dd/mm/yyyy') - to_date('26/10/2019','dd/mm/yyyy') a from dual
Table Name: MY_DATES
NM DATE_REGISTERED
--- ---------------
A1 26/10/2019
A1 2/11/2019
A1 2/02/2020
A1 9/02/2020
A1 16/02/2020
A1 23/02/2020
A1 1/03/2020
A1 8/03/2020
此练习的最终结果是 return 满足此条件的不同 NM 值数据。
这似乎很奇怪。我在想 lead()
和 lag)
。如果你想要满足条件的nm
值:
select md.*
from (select md.*,
lead(date_registered, 2) over (partition by nm order by date_registered) as next_dr_2,
lag(date_registered) over (partition by nm order by date_registered) as prev_dr
from my_dates md
) md
where prev_dr is null and
next_dr_2 > date_registered + interval '91' day;
这是一个使用 MATCH_RECOGNIZE 子句的高效解决方案,在 Oracle 版本 12.1 中引入。
WITH 子句模拟输入数据(它不是解决方案的一部分 - 删除它并在主查询中引用您的实际 table 和列名)。
解决方案按 NM 分区并按 DT 排序,然后它查找连续的三行,其中第三个日期比第一个日期晚了 13 周以上。一旦发现这样的事件,它就会用分区中所有剩余的行填充 "match pattern",基本上将它们丢弃 - 因为我们只关心单个匹配项。
注意我添加的两个 NM。 BB 确实有相隔超过 13 周的日期,但不在连续三个日期内。 CC 有两个连续的日期已经相隔超过 13 周; CC 不在输出中,因为没有三个不同的日期开始。 (注意 - 这就是我阅读要求的方式;如果需要的是 "consecutive dates more than 13 weeks apart should also count",那可以很容易地解决 - 但这不是张贴者问题中的措辞。)
with
my_dates (nm, date_registered) as (
select 'A1', to_date('26/10/2019', 'dd/mm/yyyy') from dual union all
select 'A1', to_date( '2/11/2019', 'dd/mm/yyyy') from dual union all
select 'A1', to_date( '2/02/2020', 'dd/mm/yyyy') from dual union all
select 'A1', to_date( '9/02/2020', 'dd/mm/yyyy') from dual union all
select 'A1', to_date('16/02/2020', 'dd/mm/yyyy') from dual union all
select 'A1', to_date('23/02/2020', 'dd/mm/yyyy') from dual union all
select 'A1', to_date( '1/03/2020', 'dd/mm/yyyy') from dual union all
select 'A1', to_date( '8/03/2020', 'dd/mm/yyyy') from dual union all
select 'BB', to_date( '2/03/2019', 'dd/mm/yyyy') from dual union all
select 'BB', to_date('14/03/2019', 'dd/mm/yyyy') from dual union all
select 'BB', to_date('18/03/2019', 'dd/mm/yyyy') from dual union all
select 'BB', to_date('10/06/2019', 'dd/mm/yyyy') from dual union all
select 'BB', to_date( '3/04/2019', 'dd/mm/yyyy') from dual union all
select 'CC', to_date('15/08 2019', 'dd/mm/yyyy') from dual union all
select 'CC', to_date('15/02/2020', 'dd/mm/yyyy') from dual
)
-- end of sample data (for testing only); query begins below this comment
select nm
from my_dates
match_recognize(
partition by nm
order by date_registered
pattern ( a b c x* )
define c as date_registered > a.date_registered + 91
);
NM
----
A1
** 编辑 **
重新阅读问题,似乎只应考虑 前三个日期 (而不是 任何三个连续的 日期) .
这样问题就简单多了。并且解决方案可以轻松修改 - 唯一需要更改的是 pattern
子句,它应该变成:
pattern ( ^ a b c )
这会将对三行的搜索定位在分区的开头。其他行未检查。
给定 table 中的以下示例记录:MY_DATES,使用 Oracle SQL and/or PL/SQL,我需要一直拿这个table中的第一个DATE_REGISTERED,即26/10/2019,然后前进到第三个DATE_REGISTEREDrecord/value,即2/02/ 2020 并检查它们之间的差异是否大于 13 周,即
select to_date('2/02/2020','dd/mm/yyyy') - to_date('26/10/2019','dd/mm/yyyy') a from dual
Table Name: MY_DATES
NM DATE_REGISTERED
--- ---------------
A1 26/10/2019
A1 2/11/2019
A1 2/02/2020
A1 9/02/2020
A1 16/02/2020
A1 23/02/2020
A1 1/03/2020
A1 8/03/2020
此练习的最终结果是 return 满足此条件的不同 NM 值数据。
这似乎很奇怪。我在想 lead()
和 lag)
。如果你想要满足条件的nm
值:
select md.*
from (select md.*,
lead(date_registered, 2) over (partition by nm order by date_registered) as next_dr_2,
lag(date_registered) over (partition by nm order by date_registered) as prev_dr
from my_dates md
) md
where prev_dr is null and
next_dr_2 > date_registered + interval '91' day;
这是一个使用 MATCH_RECOGNIZE 子句的高效解决方案,在 Oracle 版本 12.1 中引入。
WITH 子句模拟输入数据(它不是解决方案的一部分 - 删除它并在主查询中引用您的实际 table 和列名)。
解决方案按 NM 分区并按 DT 排序,然后它查找连续的三行,其中第三个日期比第一个日期晚了 13 周以上。一旦发现这样的事件,它就会用分区中所有剩余的行填充 "match pattern",基本上将它们丢弃 - 因为我们只关心单个匹配项。
注意我添加的两个 NM。 BB 确实有相隔超过 13 周的日期,但不在连续三个日期内。 CC 有两个连续的日期已经相隔超过 13 周; CC 不在输出中,因为没有三个不同的日期开始。 (注意 - 这就是我阅读要求的方式;如果需要的是 "consecutive dates more than 13 weeks apart should also count",那可以很容易地解决 - 但这不是张贴者问题中的措辞。)
with
my_dates (nm, date_registered) as (
select 'A1', to_date('26/10/2019', 'dd/mm/yyyy') from dual union all
select 'A1', to_date( '2/11/2019', 'dd/mm/yyyy') from dual union all
select 'A1', to_date( '2/02/2020', 'dd/mm/yyyy') from dual union all
select 'A1', to_date( '9/02/2020', 'dd/mm/yyyy') from dual union all
select 'A1', to_date('16/02/2020', 'dd/mm/yyyy') from dual union all
select 'A1', to_date('23/02/2020', 'dd/mm/yyyy') from dual union all
select 'A1', to_date( '1/03/2020', 'dd/mm/yyyy') from dual union all
select 'A1', to_date( '8/03/2020', 'dd/mm/yyyy') from dual union all
select 'BB', to_date( '2/03/2019', 'dd/mm/yyyy') from dual union all
select 'BB', to_date('14/03/2019', 'dd/mm/yyyy') from dual union all
select 'BB', to_date('18/03/2019', 'dd/mm/yyyy') from dual union all
select 'BB', to_date('10/06/2019', 'dd/mm/yyyy') from dual union all
select 'BB', to_date( '3/04/2019', 'dd/mm/yyyy') from dual union all
select 'CC', to_date('15/08 2019', 'dd/mm/yyyy') from dual union all
select 'CC', to_date('15/02/2020', 'dd/mm/yyyy') from dual
)
-- end of sample data (for testing only); query begins below this comment
select nm
from my_dates
match_recognize(
partition by nm
order by date_registered
pattern ( a b c x* )
define c as date_registered > a.date_registered + 91
);
NM
----
A1
** 编辑 **
重新阅读问题,似乎只应考虑 前三个日期 (而不是 任何三个连续的 日期) .
这样问题就简单多了。并且解决方案可以轻松修改 - 唯一需要更改的是 pattern
子句,它应该变成:
pattern ( ^ a b c )
这会将对三行的搜索定位在分区的开头。其他行未检查。