sql - 返回具有 3 个或更多遵循模式的连续值的行

标签 sql oracle

我尝试了 Tababitosan 方法但没有帮助。您能否针对以下情况提出其他解决方案。

使用 Oracle 11g:

请找到下表格式,

Region  Date      Value
East    1/1/2018    1
East    1/2/2018    1
East    1/3/2018    0
East    1/4/2018    1
East    1/6/2018    1
East    1/7/2018    0
West    1/9/2018    0
West    1/10/2018   0
West    2/3/2018    1
West    2/4/2018    1
West    2/5/2018    1
West    2/8/2018    0
West    2/9/2018    0
West    2/10/2018   0
West    2/11/2018   1
West    2/12/2018   0
West    2/13/2018   1
West    2/14/2018   1
West    2/17/2018   0
West    2/18/2018   0
West    2/19/2018   1
West    2/20/2018   0
West    2/21/2018   1
West    2/22/2018   0
West    2/23/2018   1

我的输出应包含具有三个或更多连续 1 的行以及 1 之间仅包含一个 0 的行。

注意:按地区分组并按日期排序。 日期列中的日期可能不包含所有日期。假设上面的 1/6/2018 缺失了,这很好。我需要查找按日期排序并按区域分组时遵循模式的“值”列。

East    1/1/2018    1
East    1/2/2018    1
East    1/3/2018    0
East    1/4/2018    1
East    1/6/2018    1

West    2/3/2018    1
West    2/4/2018    1
West    2/5/2018    1

West    2/11/2018   1
West    2/12/2018   0
West    2/13/2018   1
West    2/14/2018   1

West    2/19/2018   1
West    2/20/2018   0
West    2/21/2018   1
West    2/22/2018   0
West    2/23/2018   1

最佳答案

由于要求值被“屏蔽”——在某些条件下 0 变为 1,问题变得更加复杂。否则,这将是直接应用 tababitosan 方法。此外,在最终输出中,您需要原始值,而不是屏蔽值,因此我们必须小心每一步保留的内容和丢弃的内容。

这是解决该问题的一种方法。请注意,DATE 是 Oracle 关键字,因此不应将其用作列名(它可能不会引发语法错误,但会使代码更难理解)。我没有检查 VALUE 是否也是关键字;为了安全起见,我将两个列名称都更改为 DTVAL。 (正如您将看到的,在我的代码中,我分别为组和计数创建列 GRPCTGROUPCOUNT 是 Oracle 关键字,因此同样需要考虑。)

with
  inputs(region, dt, val) as (
    select 'East', to_date('1/1/2018' , 'mm/dd/yyyy'), 1 from dual union all
    select 'East', to_date('1/2/2018' , 'mm/dd/yyyy'), 1 from dual union all
    select 'East', to_date('1/3/2018' , 'mm/dd/yyyy'), 0 from dual union all
    select 'East', to_date('1/4/2018' , 'mm/dd/yyyy'), 1 from dual union all
    select 'East', to_date('1/6/2018' , 'mm/dd/yyyy'), 1 from dual union all
    select 'East', to_date('1/7/2018' , 'mm/dd/yyyy'), 0 from dual union all
    select 'West', to_date('1/9/2018' , 'mm/dd/yyyy'), 0 from dual union all
    select 'West', to_date('1/10/2018', 'mm/dd/yyyy'), 0 from dual union all
    select 'West', to_date('2/3/2018' , 'mm/dd/yyyy'), 1 from dual union all
    select 'West', to_date('2/4/2018' , 'mm/dd/yyyy'), 1 from dual union all
    select 'West', to_date('2/5/2018' , 'mm/dd/yyyy'), 1 from dual union all
    select 'West', to_date('2/8/2018' , 'mm/dd/yyyy'), 0 from dual union all
    select 'West', to_date('2/9/2018' , 'mm/dd/yyyy'), 0 from dual union all
    select 'West', to_date('2/10/2018', 'mm/dd/yyyy'), 0 from dual union all
    select 'West', to_date('2/11/2018', 'mm/dd/yyyy'), 1 from dual union all
    select 'West', to_date('2/12/2018', 'mm/dd/yyyy'), 0 from dual union all
    select 'West', to_date('2/13/2018', 'mm/dd/yyyy'), 1 from dual union all
    select 'West', to_date('2/14/2018', 'mm/dd/yyyy'), 1 from dual union all
    select 'West', to_date('2/17/2018', 'mm/dd/yyyy'), 0 from dual union all
    select 'West', to_date('2/18/2018', 'mm/dd/yyyy'), 0 from dual union all
    select 'West', to_date('2/19/2018', 'mm/dd/yyyy'), 1 from dual union all
    select 'West', to_date('2/20/2018', 'mm/dd/yyyy'), 0 from dual union all
    select 'West', to_date('2/21/2018', 'mm/dd/yyyy'), 1 from dual union all
    select 'West', to_date('2/22/2018', 'mm/dd/yyyy'), 0 from dual union all
    select 'West', to_date('2/23/2018', 'mm/dd/yyyy'), 1 from dual
  )
, prep(region, dt, val, adj_val) as (
    select region, dt, val,
           case when val = 1
                or   lag(val)  over (partition by region order by dt) = 1
                     and
                     lead(val) over (partition by region order by dt) = 1
                then 1 else 0 end
    from   inputs
  )
, tabibitosan(region, dt, val, adj_val, grp) as (
    select region, dt, val, adj_val,
           row_number() over (partition by region order by dt)
           - row_number() over (partition by region, adj_val order by dt)
    from   prep
  )
, group_counts(region, dt, val, ct) as (
    select region, dt, val, count(*) over (partition by region, grp)
    from   tabibitosan
    where  adj_val = 1
  )
select   region, dt, val
from     group_counts
where    ct >= 3
order by region, dt
;

输出:

REGION DT               VAL
------ --------- ----------
East   01-Jan-18          1
East   02-Jan-18          1
East   03-Jan-18          0
East   04-Jan-18          1
East   06-Jan-18          1
West   03-Feb-18          1
West   04-Feb-18          1
West   05-Feb-18          1
West   11-Feb-18          1
West   12-Feb-18          0
West   13-Feb-18          1
West   14-Feb-18          1
West   19-Feb-18          1
West   20-Feb-18          0
West   21-Feb-18          1
West   22-Feb-18          0
West   23-Feb-18          1

关于sql - 返回具有 3 个或更多遵循模式的连续值的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54112908/

相关文章:

SQL 和唯一的 n 列组合

sql - 交换分区时,交换的记录是否保留在原始分区中?

mysql - 无法创建 SQL 表 [SQL]

MySQL 事务返回错误

c# - 在按钮上单击从表内的许多控件插入多个(文本框和标签)文本

c# - 从 C# 中具有相同主键的两个表中获取不同的列值

sql - 如何对同一个表中三个不同查询的结果求和

sql - 将文件插入 Postgres 数据库

sql - Oracle REPLACE() 函数不处理回车符和换行符

oracle - 尝试将列从 VARCHAR2(200) 修改为 VARCHAR2(1000) 时,为什么会出现 "ORA-01429: Index-Organized Table"?