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

时间:2017-12-26 14:27:21

标签: sql oracle

考虑一个包含datestatus列的表格(可能的值为AB)。在对该表进行排序后,我想获得值status的{​​{1}}的大多数连续值。

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

A

将返回3(标有星号)。

由于我对SQL的知识非常有限,我完全不知道如何实现这一目标。我怀疑它与分区和分组有关,但就我而言。当然,我想避免使用A B B A* A* A* B B 的解决方案,然后对结果集进行后处理,除非由于某些原因尚未发现它被证明是最好的。

测试表:

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;

感谢您的帮助! :)

2 个答案:

答案 0 :(得分:3)

注意从原始答案中编辑 - 我错过了OP需要最长字符串A' a的事实,而不是具有相同状态的最长字符串。 结束注释

这是Tabibitosan方法的完美应用(使用相同排序的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'
)
;

答案 1 :(得分:2)

您需要一个指定排序的列,因为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