Oracle通过连续的日期块选择数据

时间:2017-11-15 20:51:56

标签: sql oracle

我正在使用Oracle数据库,我有一个包含2列数据的表,如下所示:

HASH | DATE
-----------------
abcd | 2017-11-01
abcd | 2017-11-02
abcd | 2017-11-03
wxyz | 2017-11-04
wxyz | 2017-11-05
abcd | 2017-11-06
wxyz | 2017-11-07
abcd | 2017-11-08
abcd | 2017-11-09
lmno | 2017-11-10
lmno | 2017-11-11

我想知道看到每个哈希的时间窗口。所以喜欢

hash | start      | end
------------------------------
abcd | 2017-11-01 | 2017-11-03
wxyz | 2017-11-04 | 2017-11-05
abcd | 2017-11-06 | 2017-11-06
wxyz | 2017-11-07 | 2017-11-07
abcd | 2017-11-08 | 2017-11-09
lmno | 2017-11-10 | 2017-11-11

到目前为止,基本上是这样的:

SELECT HASH, MIN(DATE) ST, MAX(DATE) ED
FROM HASH_TABLE 
GROUP BY HASH 
ORDER BY 3 DESC

这几乎可以工作,但它会让我喜欢" abcd"作为2017-11-01的开始和2017-11-09的结束,"隐藏"它在中间切换的事实。

是否有某种方法可以按照连续的日期/时间对这些结果进行分组" block"?

2 个答案:

答案 0 :(得分:2)

看起来像“差距和岛屿”问题:

WITH cte("hash","date") AS (
    SELECT 'abcd',  DATE'2017-11-01' FROM dual UNION ALL
    SELECT 'abcd',  DATE'2017-11-02' FROM dual UNION ALL
    SELECT 'abcd',  DATE'2017-11-03' FROM dual UNION ALL
    SELECT 'wxyz',  DATE'2017-11-04' FROM dual UNION ALL
    SELECT 'wxyz',  DATE'2017-11-05' FROM dual UNION ALL
    SELECT 'abcd',  DATE'2017-11-06' FROM dual UNION ALL
    SELECT 'wxyz',  DATE'2017-11-07' FROM dual UNION ALL
    SELECT 'abcd',  DATE'2017-11-08' FROM dual UNION ALL
    SELECT 'abcd',  DATE'2017-11-09' FROM dual UNION ALL
    SELECT 'lmno',  DATE'2017-11-10' FROM dual UNION ALL
    SELECT 'lmno',  DATE'2017-11-11' FROM dual 
)
select "hash"
      ,min("date") as startdate
      ,max("date") as enddate
from (
    select "date","hash"
         , row_number() over (order by "date") 
         - row_number() over (partition by "hash" order by "date") as grp
    from cte
) A
group by "hash", grp
ORDER BY startdate;

<强> DBFiddle Demo

答案 1 :(得分:0)

  

desc hash_table

     

hash varchar2(4)
   date_ date

select hash, min(date_) start_, max(date_) end_
  from
    (
     select h.hash, h.date_, row_number() over (partition by hash order by date_) rn
       from hash_table h 
    )
  group by hash, date_ - rn
  order by 2;