Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Form three columns table from a column table

I have a noobie question:

I need to write SQL script that returns 3 columns results set from a given one column table @T with integer field N, e.g.:

declare @t table(n int) 
insert into @t(n) values (3),(4),(5),
                         (6),(7),(8),
                         (9),(10),(11),
                         (13),(14),(15),
                         (16),(17),(18), (19)

The result 3 columns table should contains data from the table @T row by row in ascending order. If there is a missed values (e.g. {2,4} 3 is missing here) in the table @T, then the corresponding cell in result set should be NULL.

Example 1:
For table with values {2,3,4,5} the result table should looks like:

NULL    2   3 
4    5  NULL 

Example 2: For table with values {2,4} the result table should looks like:

NULL    2   NULL 
4    NULL  NULL 
like image 553
seteh Avatar asked Feb 22 '23 01:02

seteh


1 Answers

You can use a numbers table like this:

select T1.n, 
       T2.n, 
       T3.n 
from Numbers as N
  left outer join @T as T1
    on N.Number * 3 + 1 = T1.n
  left outer join @T as T2
    on N.Number * 3 + 2 = T2.n
  left outer join @T as T3
    on N.Number * 3 + 3 = T3.n
where N.Number between 0 and (select max(n) from @T) / 3

Working sample using master..spt_values as a numbers table.

declare @t table(n int) 
insert into @t(n) values (3),(4),(5),
                         (6),(7),(8),
                         (9),(10),(11),
                         (13),(14),(15),
                         (16),(17),(18), (19)


;with Numbers(Number) as
(
  select number
  from master..spt_values
  where type = 'P'
)

select T1.n, 
       T2.n, 
       T3.n 
from Numbers as N
  left outer join @T as T1
    on N.Number * 3 + 1 = T1.n
  left outer join @T as T2
    on N.Number * 3 + 2 = T2.n
  left outer join @T as T3
    on N.Number * 3 + 3 = T3.n
where N.Number between 0 and (select max(n) from @T) / 3

Or you can use a numbers table with pivot:

select [1], [2], [3]
from
  (
    select (N.Number - 1) / 3 as Number,
           T.n,
           1 + ((N.Number - 1) % 3) as rn
    from Numbers as N
      left outer join @T as T on
        N.Number = T.n
    where N.Number between 1 and (select max(n) from @T)
  ) as T
pivot
  (min(n) for rn in ([1], [2], [3])) as P
like image 188
Mikael Eriksson Avatar answered May 26 '23 08:05

Mikael Eriksson