views:

156

answers:

3

This may not be possible, but I thought I'd throw it out here:

Given the following table:

ID, Begin, End
123, 1, N

Where N is an integer, write a query to return the following result set:

ID, Begin, End
123, 1, 1
123, 1, 2
123, 1, 3
.
.
.
123, 1, N

The platform we are using is SQL Server 2005, but if you can do it with another flavor of SQL, I'd still be interested in the solution.

+1  A: 

Given some (theoretically infinite, but you could pre-populate) table Integers, containing all the integers, the answer is reasonably simple:

SELECT ID, Begin, I FROM YourTable, Integers
WHERE I <= Begin AND I >= End

With a clustered index on Integers.I, this should be pretty fast. You could pre-populate integers in a stored-proc (based on the result from SELECT max(End) FROM YourTable).

jwoolard
+1  A: 

This will work up to 99,999, and you can easily modify it to add more numbers. It needs no pre-existing numbers table and no stored procedure, and is still incredibly fast. Works on at least SQL Server 2000 and up, and is easily ported to other flavours of SQL:

select MyTable.ID, MyTable.[Begin], n.N
from (
    select 123 as ID, 1 as [Begin], 9 as [End]
) MyTable
cross join (
    select a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a) + (10000 * e.a) as N
    from (select 0 as a union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) as a
    cross join (select 0 as a union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) as b
    cross join (select 0 as a union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) as c
    cross join (select 0 as a union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) as d
    cross join (select 0 as a union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) as e
) n
where n.N > 0
    and n.N <= MyTable.[End]
order by n.N
RedFilter
A: 

try this:

create table #smalltable (id int, [begin] int, [end] int)
insert into #smalltable values (123,1,4)
insert into #smalltable values (124,1,12)
insert into #smalltable values (125,1,7)

;WITH digits (d) AS (
    SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION
    SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION
    SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION
    SELECT 0)
SELECT
    s.id, s.[begin], n.Number AS [End]
    FROM (SELECT i.d + ii.d * 10 + iii.d * 100 + iv.d * 1000 +
              v.d * 10000 + vi.d * 100000 AS Number
              FROM digits            i
                  CROSS JOIN digits  ii
                  CROSS JOIN digits  iii
                  CROSS JOIN digits  iv
                  CROSS JOIN digits  v
                  CROSS JOIN digits  vi
         ) AS N
        INNER JOIN #smalltable                                    s  ON 1=1
        INNER JOIN (SELECT MAX([end]) AS MaxEnd FROM #smalltable) dt ON 1=1
   WHERE n.Number > 0 AND n.Number<=dt.MaxEnd
    AND n.Number<=s.[end]
   ORDER BY s.id,n.Number

comments

  • don't name your columns the reserved words: "begin" and "end", you'll thank me some day.
  • if you plan to run this in production many times, create a Numbers table
    and use this query instead:

have to have a table Numbers before this will work (see link above)

SELECT
    s.id,s.[begin],n.Number AS [End]
    FROM Numbers                n
        INNER JOIN #smalltable  s ON 1=1
   WHERE  n.Number > 0 AND n.Number<=s.[end]
   ORDER BY s.id,number

it will run better.

KM
Thanks, everyone, for the solutions. This is a great place!
Richard Thomas