views:

44

answers:

3

Hello

I have a records like this:

start, end , total  
 830 , 1300,   5
 1400, 1430,   2

that I'd like to expand to:

instance , total  
  830    ,   5
  831    ,   5
  832    ,   5
  ...
  1299   ,   5
  1300   ,   5

  1400   ,   2
  1401   ,   2
  ...
  1429   ,   2
  1430   ,   2

How can I do this using SQL in MSSQL 2005?

EDIT: thanks everyone, great answers. Got a few to work. I just forgot to say though that the start/end was really a time stored as an int, so 0830 to 1300 should go upto 0859 then 0900. I can't expect you guys to answer that in this same question, i'll work around it. Thanks again

+1  A: 

This should do the trick:

create table input (start int, [end] int, total int)

insert input values (830, 1300, 5)
insert input values (1400, 1430, 2)

declare @output table (instance int, start int, [end] int, total int)

insert @output select start, start, [end], total from input

while @@rowcount > 0
    insert @output
    select
        max(instance) + 1,
        start,
        [end],
        total
    from @output
    group by
        start,
        [end],
        total
    having max(instance) < [end]

select instance, total from @output order by instance

This outputs the same (untruncated) results as you described in the question.

There might be some fancy CTE approach but I don't think that could work since you'd need an indefinite amount of recursion.

Daniel Renshaw
Thanks, that looks good.
Igor K
A: 

Assuming there is a finite max to your END values, you can use a numbers table (change the 2000 I used to be your max END value):

declare @Test table (
    start int,
    [end] int,
    total int
)

insert into @Test
    (start, [end], total)
    select 830, 1300, 5
    union
    select 1400, 1430, 2

;WITH Nbrs ( n ) AS (
        SELECT 1 UNION ALL
        SELECT 1 + n FROM Nbrs WHERE n < 2000
)
select n.n, t.total
    from @Test t
        cross join Nbrs n
    where n.n between t.start and t.[end]
    option (MAXRECURSION 2000)
Joe Stefanelli
Thanks Joe, another approach
Igor K
Note: this will only work as long as the maximum gap between `start` and `end` is less than 2000.
Daniel Renshaw
@Daniel, you are correct. I assumed (and edited my answer to reflect this assumption) that END would have some finite max. value. You'd then change 2000 to be that max.
Joe Stefanelli
The maximum `MAXRECURSION` value supported by SQL Server 2005/8 is 32,767.
Daniel Renshaw
+1  A: 

Using a CTE:

with number_cte(n) as 
 (select n from (select 0 n) m union all select n+1 n
  from number_cte where n< 2400)
select start+n instance, total
from 
datatable
join number_cte on start+n between start and [end]
where start+n - 100*floor((start+n)/100) between 0 and 59
order by 1
option (maxrecursion 2401)

(Increase n< ... and maxrecursion numbers as appropriate, if ranges greater than 2400 are required.)

Edited to prevent non-valid Instance (ie. time values ending between 60 and 99) values being included.

Mark Bannister
Thanks, that looks great but I dont understand how I'd use it:select start+n instance, total - I'm selecting a start, end and total, how do I do this?
Igor K
Please note that this is limited in the same way as Joe's answer.
Daniel Renshaw
@Igor, `datatable` is my name for the table or query you use to get your start, end and total values. Assuming they are actually called start, end and total, just replace my `datatable` with your table name or query, as appropriate. (`n` comes from my CTE, while `instance` is the column name for the result of the expression `start+n`.
Mark Bannister
@Daniel, yes - but in a time-as-minutes integer, there should never be values higher than 2400.
Mark Bannister
@Mark: ah yes, I see that info was added to the question
Daniel Renshaw