【问题标题】:Oracle - Count consecutive days meeting the same given criteriaOracle - 计算满足相同给定条件的连续天数
【发布时间】:2015-06-09 12:08:12
【问题描述】:

我的 Oracle 数据库中有以下结构:

Date          Allocation  id
2015-01-01    Same        200
2015-01-02    Good        200
2015-01-03    Same        200
2015-01-04    Same        200
2015-01-05    Same        200
2015-01-06    Good        200

我想要一个查询,它只需要检查前连续几天并获取分配为"Same" 的计数。

我想按日期选择,例如2015-01-05
示例输出:对于日期2015-01-05,计数为3

新问题。通过 Lukas Eder 的查询,计数始终为 12。但预期是3。从 2015 年 1 月 3 日到 2015 年 1 月 5 日。

Date          Allocation  id
2015-01-01    Same        400
2015-01-02    Good        400
2015-01-03    Same        400
2015-01-04    Same        400
2015-01-05    Same        400
2015-01-06    Good        400

来自 Lukas Eder 的代码

 SELECT c
    FROM (
      SELECT allocation, d, count(*) OVER (PARTITION BY allocation, part ORDER BY d) AS c
      FROM (
        SELECT allocation, d,
               d - row_number() OVER (PARTITION BY allocation ORDER BY d) AS part
        FROM t
      )
    )
    WHERE d = DATE '2015-01-05';

【问题讨论】:

标签: sql oracle


【解决方案1】:

试一试:

    create table mbtmp(d_date date, alloc varchar2(20), id number);

insert into mbtmp values (to_date('2015-01-01','yyyy-mm-dd'),'SAME',200);
insert into mbtmp values (to_date('2015-01-02','yyyy-mm-dd'),'GOOD',200);
insert into mbtmp values (to_date('2015-01-03','yyyy-mm-dd'),'SAME',200);
insert into mbtmp values (to_date('2015-01-04','yyyy-mm-dd'),'SAME',200);
insert into mbtmp values (to_date('2015-01-05','yyyy-mm-dd'),'SAME',200);
insert into mbtmp values (to_date('2015-01-06','yyyy-mm-dd'),'GOOD',200);
COMMIT;

SELECT max(length(sames) - length(replace(sames,'|',null)) - 1) from ( 
select regexp_substr( pth,'[|SAME]+') sames 
FROM(
   SELECT sys_connect_by_path(alloc,'|') pth  
    from mbtmp m
    WHERE d_Date > ( select max(d_date) from mbtmp 
                     where d_Date < to_date('2015-01-05','yyyy-mm-dd')
                      And alloc != 'SAME' )
    START WITH d_Date = to_date('2015-01-05','yyyy-mm-dd')
    CONNECT BY Prior d_date = d_date + 1));

现在,如果不是连续天规则,即 - 如果即使天数列表中存在间隙,您仍然计算在内,那么您可以使用更简单的查询:

select count(d_Date)
    FROM mbtmp
    WHERE d_Date > ( select max(d_date) from mbtmp 
                      where d_Date < to_date('2015-01-05','yyyy-mm-dd')
                      And alloc != 'SAME' )
    and   d_date <= to_date('2015-01-05','yyyy-mm-dd') 

【讨论】:

    【解决方案2】:

    您可以使用不同的行来识别组。这就是您的查询正在做的事情。如果您想要特定日期的值,请使用:

    select t.*
    from (select t.*,
                 (row_number() over (order by date) -
                  row_number() over (partition by allocation order by date)
                 ) as grp
          from table t
         ) t
    where d = date '2015-01-05';
    

    关于为什么您的问题中的版本不起作用,我最好的猜测是因为您的 date 可能有时间组件。我假设ddate 列。

    编辑:

    要获取计数,请使用子查询和count(*) 作为分析函数:

    select t.*
    from (select t.*, count(*) over (partition by grp, allocation) as cnt
          from (select t.*,
                       (row_number() over (order by date) -
                        row_number() over (partition by allocation order by date)
                       ) as grp
                from table t
               ) t
          ) t
    where d = date '2015-01-05';
    

    或者,如果你只想要计数,你可以使用聚合:

          select date, count(*) as cnt
          from (select t.*,
                       (row_number() over (order by date) -
                        row_number() over (partition by allocation order by date)
                       ) as grp
                from table t
               ) t
          group by date, allocation
          having date = date '2015-01-05';
    

    【讨论】:

    • 谢谢。这并没有给我连续几天使用的“相同”计数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-11
    • 1970-01-01
    • 2019-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多