Bhushan
Bhushan

Reputation: 43

Merge rows based on date in SQL Server

I want to display data based on start date and end date. a code can contain different dates. if any time intervel is continues then I need to merge that rows and display as single row Here is sample data

Code  Start_Date   End_Date     Volume
470   24-Oct-10    30-Oct-10    28
470   17-Oct-10    23-Oct-10     2
470   26-Sep-10     2-Oct-10     2
471   22-Aug-10    29-Aug-10     2
471   15-Aug-10    21-Aug-10     2

The output result I want is

Code  Start_Date   End_Date     Volume
470   17-Oct-10    30-Oct-10    30
470   26-Sep-10     2-Oct-10     2
471   15-Aug-10    29-Aug-10     4

a code can have any no. of time intervels. Pls help. Thank you

Upvotes: 4

Views: 4224

Answers (2)

Damien_The_Unbeliever
Damien_The_Unbeliever

Reputation: 239636

Based on your sample data (which I've put in a table called Test), and assuming no overlaps:

;with Ranges as (
    select Code,Start_Date,End_Date,Volume from Test
    union all
    select r.Code,r.Start_Date,t.End_Date,(r.Volume + t.Volume)
    from
        Ranges r
            inner join
        Test t
            on
                r.Code = t.Code and
                DATEDIFF(day,r.End_Date,t.Start_Date) = 1
), ExtendedRanges as (
select Code,MIN(Start_Date) as Start_Date,End_Date,MAX(Volume) as Volume
from Ranges
group by Code,End_Date
)
select Code,Start_Date,MAX(End_Date),MAX(Volume)
from ExtendedRanges
group by Code,Start_Date

Explanation:

The Ranges CTE contains all rows from the original table (because some of them might be relevant) and all rows we can form by joining ranges together (both original ranges, and any intermediate ranges we construct - we're doing recursion here).

Then ExtendedRanges (poorly named) finds, for any particular End_Date, the earliest Start_Date that can reach it.

Finally, we query this second CTE, to find, for any particular Start_Date, the latest End_Date that is associated with it.

These two queries combine to basically filter the Ranges CTE down to "the widest possible Start_Date/End_Date pair" in each set of overlapping date ranges.

Sample data setup:

create table Test (
    Code int not null,
    Start_Date date not null,
    End_Date date not null,
    Volume int not null
)
insert into Test(Code,  Start_Date,   End_Date,     Volume)
select 470,'24-Oct-10','30-Oct-10',28 union all
select 470,'17-Oct-10','23-Oct-10',2 union all
select 470,'26-Sep-10','2-Oct-10',2 union all
select 471,'22-Aug-10','29-Aug-10',2 union all
select 471,'15-Aug-10','21-Aug-10',2
go

Upvotes: 4

Ralph Shillington
Ralph Shillington

Reputation: 21098

if I understand your request, you're looking for something like:

select code, min(Start_date), max(end_date), sum(volume)
from yourtable
group by code

Upvotes: 3

Related Questions