Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
459 views
in Technique[技术] by (71.8m points)

sql - MSSQL dynamic pivot column values to column header

Could someone help me convert the following on mssql please?

 ID   |  PROPERTY_NAME  | PROPERTY_VALUE
 1    |      name1      |     value
 1    |      name2      |     value
 1    |      name3      |     value
 2    |      name4      |     value
 2    |      name2      |     value
 3    |      name6      |     value
..

PROPERTY_NAME & PROPERTY_VALUE being the headers, id having multiple 'properties'

I want to convert it to:

ID  |  NAME1  | NAME2  | NAME3  | NAME4  | NAME5  | NAME6  | nameETC...
1   |  value  | value  | value  |        |        |        | valueETC...
2   |         | value  |        | value  |        |        | valueETC...
3   |         |        |        |        |        | value  | valueETC...
..

Where NAME1 | NAME2 | NAME3 etc are now the column headers.

I'm guessing a pivot and a 'select distinct PROPERTY_NAME from MycoolTable' but can't seem to put the two together.

This is as far as i got: (no server_id) column and all nulls everywhere) Clearly i'm stupid :D

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

select @cols = STUFF((SELECT distinct 
           ',' + QUOTENAME(PROPERTY_NAME)
               FROM [BSARA_DW_DB].[dbo].[SERVER_PROPERTY]
               FOR XML PATH(''), TYPE
               ).value('.', 'NVARCHAR(MAX)') 
               ,1,1,'');

SET @query = 'SELECT  '+ @cols + ' from 
         (
            SELECT SERVER_ID, PROPERTY_NAME, PROPERTY_CHAR_VAL
            FROM [BSARA_DW_DB].[dbo].[SERVER_PROPERTY]
        ) x
        pivot 
        (
            MAX(SERVER_ID)
            for PROPERTY_CHAR_VAL in (' + @cols + ')
        ) p ';

execute(@query)

Many thanks, Mike

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The problem with your current query is with the line:

MAX(SERVER_ID)

You want to display the PROPERTY_CHAR_VAL for each PROPERTY_NAME instead. The SERVER_ID will be a part of the final result as a column.

Sometimes when you are working with PIVOT is is easier to write the code first with the values hard-coded similar to:

select id, name1, name2, name3, name4
from
(
  select id, property_name, property_value
  from yourtable
) d
pivot
(
  max(property_value)
  for property_name in (name1, name2, name3, name4)
) piv;

See SQL Fiddle with Demo.

Once you have a version that has the correct logic, then you can convert it to dynamic SQL to get the result. This will create a sql string that will be executed and it will include all of your new columns names.

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

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(PROPERTY_NAME) 
                    from yourtable
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT id, ' + @cols + ' 
            from 
            (
              select id, property_name, property_value
              from yourtable
            ) x
            pivot 
            (
                max(property_value)
                for property_name in (' + @cols + ')
            ) p '

execute sp_executesql @query;

See SQL Fiddle with Demo. Both will give a result:

| ID |  NAME1 |  NAME2 |  NAME3 |  NAME4 |  NAME6 |
|----|--------|--------|--------|--------|--------|
|  1 |  value |  value |  value | (null) | (null) |
|  2 | (null) |  value | (null) |  value | (null) |
|  3 | (null) | (null) | (null) | (null) |  value |

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...