[英]Oracle - getting the number of consecutive column values within time range
考虑一个带有date
和status
列的表(可能的值为A
和B
)。 在订购该表之后,我想获取值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.