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.

2
  • Sorry to be referencing my own blog here, but this may help. Also, it appears you are looking to go from rows to columns. Commented Oct 12, 2012 at 18:43
  • @Pondlife. You are correct. This is a close duplicate to those. Thanks for the note. Commented Oct 12, 2012 at 18:59

1 Answer 1

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
Sign up to request clarification or add additional context in comments.

1 Comment

Stunning bluefeet. I swear, having stackoverflow around almost makes it so I don't have to think :-) I think this will work.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.