繁体   English   中英

Oracle-获取时间范围内连续列值的数量

[英]Oracle - getting the number of consecutive column values within time range

考虑一个带有datestatus列的表(可能的值为AB )。 在订购该表之后,我想获取值A status的最连续值的数量。

例如,下面的按日期排序结果集

A
B
B
A*
A*
A*
B
B

将返回3(标有星号)。

以我对SQL的了解非常有限,我完全不知道如何实现这一目标。 我怀疑这与分区和分组有关,但是据我所知。 当然,我希望避免使用select *的解决方案,然后对结果集进行后处理,除非由于某种原因而被证明是最好的,否则将对其进行后处理。

测试表:

CREATE TABLE TEST
(
  DATE    DATE,
  STATUS  VARCHAR2(1)
)
RESULT_CACHE (MODE DEFAULT)
STORAGE    (
        BUFFER_POOL      DEFAULT
        FLASH_CACHE      DEFAULT
        CELL_FLASH_CACHE DEFAULT
       )
LOGGING 
NOCOMPRESS 
NOCACHE
NOPARALLEL
NOMONITORING;

插入语句:

Insert into TEST
(DATE, STATUS)
 Values
(TO_DATE('06/08/2017 17:16:16', 'MM/DD/YYYY HH24:MI:SS'), 'B');
Insert into TEST
(DATE, STATUS)
 Values
(TO_DATE('04/24/2016 21:26:07', 'MM/DD/YYYY HH24:MI:SS'), 'A');
Insert into TEST
(DATE, STATUS)
 Values
(TO_DATE('04/24/2016 21:26:22', 'MM/DD/YYYY HH24:MI:SS'), 'A');
Insert into TEST
(DATE, STATUS)
 Values
(TO_DATE('04/24/2016 21:26:33', 'MM/DD/YYYY HH24:MI:SS'), 'A');
Insert into TEST
(DATE, STATUS)
 Values
(TO_DATE('04/24/2016 21:26:40', 'MM/DD/YYYY HH24:MI:SS'), 'A');
Insert into TEST
(DATE, STATUS)
 Values
(TO_DATE('04/24/2016 21:27:03', 'MM/DD/YYYY HH24:MI:SS'), 'A');
Insert into TEST
(DATE, STATUS)
 Values
(TO_DATE('04/24/2016 21:26:13', 'MM/DD/YYYY HH24:MI:SS'), 'B');
Insert into TEST
(DATE, STATUS)
 Values
(TO_DATE('04/24/2016 21:26:15', 'MM/DD/YYYY HH24:MI:SS'), 'B');
Insert into TEST
(DATE, STATUS)
 Values
(TO_DATE('04/24/2016 21:26:16', 'MM/DD/YYYY HH24:MI:SS'), 'B');

谢谢您的帮助! :)

:从最初的答案编辑 -我错过了OP想要的最长的字符串的事实A “一,没有使用相同的状态中最长的字符串。 结束注

这是Tabibitosan方法的完美应用ROW_NUMBER()在相同的顺序上使用ROW_NUMBER()值的固定差异,无论是否通过STATUS进行分区,以创建我们需要的其他分组)。 注意:我将列名从DATE更改为DT DATE是Oracle关键字,不应用作列名。

select   max(count(*)) as max_count
from     (
           select status, 
                  row_number() over (order by dt) 
                        - row_number() over (partition by status order by dt) as grp
           from   test
         )
where    status = 'A'
group by status, grp
;

在Oracle 12.1和更高版本中,可以对新的match_recoginze子句执行相同的操作:

select max(cnt) as max_count
from   test
match_recognize(
  order by dt
  measures count(*) as cnt
  pattern  ( x+ )
  define   x as status = 'A'
)
;

您需要一列来指定顺序,因为SQL表表示无序集。

您可以用不同的方式识别组。 在您的情况下,也许最简单的方法是在每个“ A”之前计算“ B”的数量-这对于“ A”序列是恒定的。 然后使用另一个窗口函数确定组中的数字:

select t.*
from (select t.*, max(cnt) over () as max_cnt
      from (select t.*, count(*) over (partition by status, grp) as cnt
            from (select t.*,
                         sum(case when status <> 'A' then 1 else 0 end) over (order by ?) as grp
                  from t
                  ) t
            where status = 'A'
           ) t
      ) t
where cnt = max_cnt;

如果只需要值“ 3”,则可以使用:

select max(cnt)
from (select t.*, count(*) over (partition by status, grp) as cnt
      from (select t.*,
                   sum(case when status <> 'A' then 1 else 0 end) over (order by ?) as grp
            from t
            ) t
      where status = 'A'
     ) t

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM