Oracle SQL-连续查找3个月
我必须写一个查询,以便按月整理记录。我只需要选择连续3个月。如果连续3个月没有发生,则查询不应拾取值Oracle SQL-连续查找3个月,sql,oracle,Sql,Oracle,我必须写一个查询,以便按月整理记录。我只需要选择连续3个月。如果连续3个月没有发生,则查询不应拾取值 COLUMN ID DATE 100 01-MAY-2015 100 01-JUN-2015 100 01-JUL-2015 100 01-AUG-2015 111 01-MAY-2015 111 01-JUN-2015
COLUMN ID DATE
100 01-MAY-2015
100 01-JUN-2015
100 01-JUL-2015
100 01-AUG-2015
111 01-MAY-2015
111 01-JUN-2015
111 01-AUG-2015
111 01-SEP-2015
122 01-APR-2015
122 01-MAY-2015
输出
COLUMN ID DATE
100 01-MAY-2015
100 01-JUN-2015
100 01-JUL-2015
任何在Oracle SQL中执行此操作的想法。提前感谢这个问题很好地说明了Oracle 12.1中引入的MATCH_Recognite子句的威力
with
inputs ( id, dt ) as (
select 100, to_date('01-MAY-2015', 'dd-MON-yyyy') from dual union all
select 100, to_date('01-JUN-2015', 'dd-MON-yyyy') from dual union all
select 100, to_date('01-JUL-2015', 'dd-MON-yyyy') from dual union all
select 100, to_date('01-AUG-2015', 'dd-MON-yyyy') from dual union all
select 111, to_date('01-MAY-2015', 'dd-MON-yyyy') from dual union all
select 111, to_date('01-JUN-2015', 'dd-MON-yyyy') from dual union all
select 111, to_date('01-AUG-2015', 'dd-MON-yyyy') from dual union all
select 111, to_date('01-SEP-2015', 'dd-MON-yyyy') from dual union all
select 122, to_date('01-APR-2015', 'dd-MON-yyyy') from dual union all
select 122, to_date('01-MAY-2015', 'dd-MON-yyyy') from dual
)
-- End of simulated inputs (for testing only, not part of the SQL query)
select id, dt
from inputs
match_recognize (
partition by id
order by dt
all rows per match
pattern ( a b b {-x*-} )
define b as dt = add_months(prev(dt), 1)
)
;
ID DT
--- -----------
100 01-MAY-2015
100 01-JUN-2015
100 01-JUL-2015
这个问题是Oracle 12.1中引入的MATCH_RECOGNIZE子句的强大功能的一个很好的例子
with
inputs ( id, dt ) as (
select 100, to_date('01-MAY-2015', 'dd-MON-yyyy') from dual union all
select 100, to_date('01-JUN-2015', 'dd-MON-yyyy') from dual union all
select 100, to_date('01-JUL-2015', 'dd-MON-yyyy') from dual union all
select 100, to_date('01-AUG-2015', 'dd-MON-yyyy') from dual union all
select 111, to_date('01-MAY-2015', 'dd-MON-yyyy') from dual union all
select 111, to_date('01-JUN-2015', 'dd-MON-yyyy') from dual union all
select 111, to_date('01-AUG-2015', 'dd-MON-yyyy') from dual union all
select 111, to_date('01-SEP-2015', 'dd-MON-yyyy') from dual union all
select 122, to_date('01-APR-2015', 'dd-MON-yyyy') from dual union all
select 122, to_date('01-MAY-2015', 'dd-MON-yyyy') from dual
)
-- End of simulated inputs (for testing only, not part of the SQL query)
select id, dt
from inputs
match_recognize (
partition by id
order by dt
all rows per match
pattern ( a b b {-x*-} )
define b as dt = add_months(prev(dt), 1)
)
;
ID DT
--- -----------
100 01-MAY-2015
100 01-JUN-2015
100 01-JUL-2015
仅使用分析函数的解决方案(应适用于Oracle 9及更高版本) 注意:我已经为Oracle 12.1及以上版本发布了另一个答案。这是一个完全不同的方法,因此它确实是一个不同的答案(即使是由同一个人发布的) 为简单起见,此查询仅返回ID和至少连续三个月的第一个月。与MATCH_Recognite解决方案一样,在该解决方案中,我们也只查找连续三个月的第一次出现。(对于同一个ID,可能有连续五个月,或者在两个不同的地方有连续三个月-我们只识别连续三个月中的第一次出现。)如果所有三行-所有三个月-都需要,这很容易适应
with
inputs ( id, dt ) as (
select 100, to_date('01-MAY-2015', 'dd-MON-yyyy') from dual union all
select 100, to_date('01-JUN-2015', 'dd-MON-yyyy') from dual union all
select 100, to_date('01-JUL-2015', 'dd-MON-yyyy') from dual union all
select 100, to_date('01-AUG-2015', 'dd-MON-yyyy') from dual union all
select 111, to_date('01-MAY-2015', 'dd-MON-yyyy') from dual union all
select 111, to_date('01-JUN-2015', 'dd-MON-yyyy') from dual union all
select 111, to_date('01-AUG-2015', 'dd-MON-yyyy') from dual union all
select 111, to_date('01-SEP-2015', 'dd-MON-yyyy') from dual union all
select 122, to_date('01-APR-2015', 'dd-MON-yyyy') from dual union all
select 122, to_date('01-MAY-2015', 'dd-MON-yyyy') from dual
)
-- End of simulated inputs (for testing only, not part of the SQL query)
select id, min(dt) as dt
from (
select id, dt,
case when lead(dt, 1) over (partition by id order by dt) = add_months(dt, 1)
and lead(dt, 2) over (partition by id order by dt) = add_months(dt, 2)
then 1
end as flag
from inputs
)
where flag = 1
group by id
;
ID DT
--- -----------
100 01-MAY-2015
仅使用分析函数的解决方案(应适用于Oracle 9及更高版本) 注意:我已经为Oracle 12.1及以上版本发布了另一个答案。这是一个完全不同的方法,因此它确实是一个不同的答案(即使是由同一个人发布的) 为简单起见,此查询仅返回ID和至少连续三个月的第一个月。与MATCH_Recognite解决方案一样,在该解决方案中,我们也只查找连续三个月的第一次出现。(对于同一个ID,可能有连续五个月,或者在两个不同的地方有连续三个月-我们只识别连续三个月中的第一次出现。)如果所有三行-所有三个月-都需要,这很容易适应
with
inputs ( id, dt ) as (
select 100, to_date('01-MAY-2015', 'dd-MON-yyyy') from dual union all
select 100, to_date('01-JUN-2015', 'dd-MON-yyyy') from dual union all
select 100, to_date('01-JUL-2015', 'dd-MON-yyyy') from dual union all
select 100, to_date('01-AUG-2015', 'dd-MON-yyyy') from dual union all
select 111, to_date('01-MAY-2015', 'dd-MON-yyyy') from dual union all
select 111, to_date('01-JUN-2015', 'dd-MON-yyyy') from dual union all
select 111, to_date('01-AUG-2015', 'dd-MON-yyyy') from dual union all
select 111, to_date('01-SEP-2015', 'dd-MON-yyyy') from dual union all
select 122, to_date('01-APR-2015', 'dd-MON-yyyy') from dual union all
select 122, to_date('01-MAY-2015', 'dd-MON-yyyy') from dual
)
-- End of simulated inputs (for testing only, not part of the SQL query)
select id, min(dt) as dt
from (
select id, dt,
case when lead(dt, 1) over (partition by id order by dt) = add_months(dt, 1)
and lead(dt, 2) over (partition by id order by dt) = add_months(dt, 2)
then 1
end as flag
from inputs
)
where flag = 1
group by id
;
ID DT
--- -----------
100 01-MAY-2015
什么版本的Oracle?根据版本的不同,可以使用不同的方法。Mathguy,我使用的是Oracle版本11g Oracle的哪个版本?根据版本的不同,可以使用不同的方法。Mathguy,我使用的是Oracle版本11gMathguy,如果我们连续需要4条或更多记录,该怎么办???这在Oracle 11g上有效吗?难以置信!在任何情况下:模式是
abb{-x*}
-这意味着,在每个分区(按id分组)中,按日期排序后,查找第一行(a
)不受限制的任何行序列;第二行和第三行均为b类
,受定义
条件限制;以及输出中未显示的任意数量的非限制行(classx
)({-…-}
表示法)。因此,如果您需要,比如说,连续四个月,将模式更改为abb{-x*-}
,连续五个月更改为abb{-x*-}
,等等。Mathguy,如果我们需要连续四行或更多记录,该如何处理???这在Oracle 11g上有效吗?难以置信!在任何情况下:模式是abb{-x*}
-这意味着,在每个分区(按id分组)中,按日期排序后,查找第一行(a
)不受限制的任何行序列;第二行和第三行均为b类
,受定义
条件限制;以及输出中未显示的任意数量的非限制行(classx
)({-…-}
表示法)。因此,如果您需要,比如说,连续四个月,将模式更改为abb{-x*-}
,连续五个月更改为abb{-x*-}
,等等。