1

Possible Duplicate:
SQL Server dynamic PIVOT query?

I have a dataset that has the below structure.

CREATE TABLE #TempTable
  (
     Measure_ID  INT,
     measurement DECIMAL(18, 4)
  )

INSERT INTO #TempTable
VALUES
(1,2.3)
,(1,3.4)
,(1,3.3)
,(2,3)
,(2,2.3)
,(2,4.0)
,(2,4.5)

I need to produce output that will look like this.

1,2.3,3.4,3.3
2,3,2.3,4.0,4.5

Basically its a pivot on Measure_ID. Unfortunately, there can be an unlimited number of measure_id's. So Pivot is out.

I'm hoping to avoid CURSORS, but will if that turns out to be the best approach.

Community
  • 1
  • 1
Dayton Brown
  • 1,228
  • 3
  • 16
  • 31
  • Sorry to be referencing my own blog here, but [this may help](http://www.jadito.us/2012/08/28/rows-to-column-header-using-dynamic-t-sql/). Also, it appears you are looking to go from rows to columns. – Kermit Oct 12 '12 at 18:43
  • @Pondlife. You are correct. This is a close duplicate to those. Thanks for the note. – Dayton Brown Oct 12 '12 at 18:59

1 Answers1

4

If you have an unknown number of values, then you can use a PIVOT with dynamic SQL:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' 
                        + QUOTENAME('Measurement_' + cast(rn as varchar(10))) 
                    from temptable
                    cross apply
                    (
                      select row_number() over(partition by measure_id order by measurement) rn
                      from temptable
                    ) x
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT measure_id, ' + @cols + ' from 
             (
                select measure_id, measurement,
                  ''Measurement_''
                    + cast(row_number() over(partition by measure_id order by measurement) as varchar(10)) val
                from temptable
            ) x
            pivot 
            (
                max(measurement)
                for val in (' + @cols + ')
            ) p '

execute(@query)

See SQL Fiddle With Demo

If you have a known number of values, then you can hard-code the values, similar to this:

SELECT measure_id, [Measurement_1], [Measurement_2], 
               [Measurement_3], [Measurement_4]
from 
(
  select measure_id, measurement,
    'Measurement_'
     + cast(row_number() over(partition by measure_id order by measurement) as varchar(10)) val
  from temptable
) x
pivot 
(
   max(measurement)
   for val in ([Measurement_1], [Measurement_2], 
               [Measurement_3], [Measurement_4])
) p 

See SQL Fiddle With Demo

Both queries will produce the same results:

MEASURE_ID | MEASUREMENT_1 | MEASUREMENT_2 | MEASUREMENT_3 | MEASUREMENT_4
==========================================================================
1          | 2.3           | 3.3           | 3.4           | (null)
2          | 2.3           | 3             | 4             | 4.5
Taryn
  • 242,637
  • 56
  • 362
  • 405
  • Stunning bluefeet. I swear, having stackoverflow around almost makes it so I don't have to think :-) I think this will work. – Dayton Brown Oct 12 '12 at 18:54