Reputation: 1132
I am using an Oracle database and I have a table that has 2 columns with data like so:
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
I want to know the windows of time that each hash is seen. So like
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
What I have so far is basically this:
SELECT HASH, MIN(DATE) ST, MAX(DATE) ED
FROM HASH_TABLE
GROUP BY HASH
ORDER BY 3 DESC
And this almost works but it will give me like "abcd" as a start of 2017-11-01 and an end of 2017-11-09 which "hides" the fact that it switched in the middle.
Is there some way to group these results by contiguous date/time "blocks"?
Upvotes: 5
Views: 237
Reputation: 175994
It looks like "gaps and islands" problem:
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;
Upvotes: 3
Reputation: 65363
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;
Upvotes: 0