July 24, 2012 at 12:24 am
The table contains start and end of the range which can be overlapping. I need a query to return the non-overlapping set of range covering the maximum range.
Table : Ranges
start end
10 20
15 20
25 40
30 40
The output should be
10 20
25 40
July 24, 2012 at 1:16 am
Try to get your hands on Itzik's book Microsoft SQL Server 2012 High-Performance T-SQL Using Window Functions. It has a few solutions for the "gaps and islands" problem.
Need an answer? No, you need a question
My blog at https://sqlkover.com.
MCSE Business Intelligence - Microsoft Data Platform MVP
July 24, 2012 at 3:20 am
Hi Below is the query for the scenario which you gave..
select a.start,a.ends from
(select *,
ROW_NUMBER() over (partition by ends order by start asc) Ranking
from ranges)a
where Ranking = 1
Regards,
Karthik.
SQL Developer.
July 24, 2012 at 7:39 am
Karthiart (7/24/2012)
Hi Below is the query for the scenario which you gave..
select a.start,a.ends from
(select *,
ROW_NUMBER() over (partition by ends order by start asc) Ranking
from ranges)a
where Ranking = 1
But it won't handle things like the following which are inevitable for such a thing...
start end
10 15
15 20
25 40
30 40
--Jeff Moden
Change is inevitable... Change for the better is not.
July 24, 2012 at 8:49 am
Here is something to start working with to solve your problem.
Read this article, http://www.sqlservercentral.com/articles/T-SQL/71550/, for more insight in to what is happening.
declare @Range table(
[StartRange] int,
[EndRange] int
);
Insert into @Range
Values
(10,20),
(15,20),
(25,40),
(30,40);
select * from @Range;
with
e1(n) as (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
e2(n) as (select 1 from e1 a cross join e1 b),
e4(n) as (select 1 from e2 a cross join e2 b),
tally(n) as (select 0 union all select row_number() over (order by (select null)) from e4 a cross join e2 b),
basedata as (
select distinct
d.StartRange + n as RangeValue
from
@Range d
cross apply (select top (d.EndRange - d.StartRange + 1) n from tally) dt(n)
),
WorkingData as (
select
RangeValue,
row_number() over (order by RangeValue) as rn
from
basedata
)
select
min(RangeValue) as StartRange,
max(RangeValue) as EndRange
from
WorkingData
group by
RangeValue - rn
order by
RangeValue - rn;
go
declare @Range table(
[StartRange] int,
[EndRange] int
);
Insert into @Range
Values
(10,15),
(15,20),
(25,40),
(30,40);
select * from @Range;
with
e1(n) as (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
e2(n) as (select 1 from e1 a cross join e1 b),
e4(n) as (select 1 from e2 a cross join e2 b),
tally(n) as (select 0 union all select row_number() over (order by (select null)) from e4 a cross join e2 b),
basedata as (
select distinct
d.StartRange + n as RangeValue
from
@Range d
cross apply (select top (d.EndRange - d.StartRange + 1) n from tally) dt(n)
),
WorkingData as (
select
RangeValue,
row_number() over (order by RangeValue) as rn
from
basedata
)
select
min(RangeValue) as StartRange,
max(RangeValue) as EndRange
from
WorkingData
group by
RangeValue - rn
order by
RangeValue - rn;
go
July 24, 2012 at 12:53 pm
Jeff Moden (7/24/2012)
Karthiart (7/24/2012)
Hi Below is the query for the scenario which you gave..
select a.start,a.ends from
(select *,
ROW_NUMBER() over (partition by ends order by start asc) Ranking
from ranges)a
where Ranking = 1
But it won't handle things like the following which are inevitable for such a thing...
start end
10 15
15 20
25 40
30 40
That's why i mentioned: "This query is for the scenario which you gave".
But then, i tested the query for your new scenario also. It works properly. Can you please tell me where it fails for the above mentioned request (scenario which you gave).
Regards,
Karthik.
SQL Developer.
July 24, 2012 at 12:58 pm
Got the Point!!
Regards,
Karthik.
SQL Developer.
July 24, 2012 at 4:39 pm
Karthiart (7/24/2012)
Got the Point!!
🙂
--Jeff Moden
Change is inevitable... Change for the better is not.
Viewing 8 posts - 1 through 8 (of 8 total)
You must be logged in to reply to this topic. Login to reply