SQL Server:Pivot with Custom Column Names

SQL Server : Pivot with custom column names

There are a few ways that you can do this.

If you had a known number of questions/answers then you could use row_number() along with an aggregate function and a CASE expression:

select id,
max(case when rn = 1 then question end) question1,
max(case when rn = 1 then answer end) answer1,
max(case when rn = 2 then question end) question2,
max(case when rn = 2 then answer end) answer2,
max(case when rn = 3 then question end) question3,
max(case when rn = 3 then answer end) answer3
from
(
select id, question, answer,
row_number() over(partition by id order by id, question) rn
from yt
) src
group by id;

See SQL Fiddle with Demo

Another suggestion would be to use both the UNPIVOT and the PIVOT function to get the result. The UNPIVOT will take your question and answer columns and convert them into multiple rows.

The basic syntax for the UNPIVOT will be:

select id,
col+cast(rn as varchar(10)) col,
value
from
(
-- when you perform an unpivot the datatypes have to be the same.
-- you might have to cast the datatypes in this query
select id, question, cast(answer as varchar(500)) answer,
row_number() over(partition by id order by id, question) rn
from yt
) src
unpivot
(
value
for col in (question, answer)
) unpiv;

See Demo. This gives a result:

|      ID |       COL |                                VALUE |
--------------------------------------------------------------
| 4482515 | question1 | I would like to be informed by mail. |
| 4482515 | answer1 | No |
| 4482515 | question2 | Plan to Purchase? |
| 4482515 | answer2 | Over 12 months |
| 4482515 | question3 | Test Question Text |
| 4482515 | answer3 | some Answer |

As you can see, I added a row_number() value to the initial subquery so you can associate each answer to the question. Once this has been unpivoted, then you can pivot the result on the new column names with the question/answer with the concatenated row number value. The code with the PIVOT syntax will be:

select id, question1, answer1, question2, answer2,
question3, answer3
from
(
select id,
col+cast(rn as varchar(10)) col,
value
from
(
-- when you perform an unpivot the datatypes have to be the same.
-- you might have to cast the datatypes in this query
select id, question, cast(answer as varchar(500)) answer,
row_number() over(partition by id order by id, question) rn
from yt
) src
unpivot
(
value
for col in (question, answer)
) unpiv
) d
pivot
(
max(value)
for col in (question1, answer1, question2, answer2,
question3, answer3)
) piv;

See SQL Fiddle with Demo. Now in your situation, you stated that you will have a dynamic number of questions/answers. If that is the case, then you will need to use dynamic SQL to get the result:

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

select @cols = STUFF((SELECT ',' + QUOTENAME(c.col+cast(rn as varchar(10)))
from
(
select row_number() over(partition by id
order by id, question) rn
from yt
) d
cross apply
(
select 'question' col, 1 sort union all select 'answer', 2
) c
group by col, rn, sort
order by rn, sort
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')

set @query = 'SELECT id, ' + @cols + '
from
(
select id,
col+cast(rn as varchar(10)) col,
value
from
(
-- when you perform an unpivot the datatypes have to be the same.
-- you might have to cast the datatypes in this query
select id, question, cast(answer as varchar(500)) answer,
row_number() over(partition by id order by id, question) rn
from yt
) src
unpivot
(
value
for col in (question, answer)
) unpiv
) d
pivot
(
max(value)
for col in (' + @cols + ')
) p '

execute(@query);

See SQL Fiddle with Demo. These give a result:

|      ID |                            QUESTION1 | ANSWER1 |         QUESTION2 |        ANSWER2 |          QUESTION3 |     ANSWER3 |
------------------------------------------------------------------------------------------------------------------------------------
| 4482515 | I would like to be informed by mail. | No | Plan to Purchase? | Over 12 months | Test Question Text | some Answer |

Pivoting rows to columns with custom column names in SQL Server

You can use row_number() and conditional aggregation:

SELECT t1.Message, a.*
FROM Table1 t1 CROSS APPLY
(SELECT MAX(CASE WHEN seqnum = 1 THEN value END) as greeting1,
MAX(CASE WHEN seqnum = 2 THEN value END) as greeting2,
MAX(CASE WHEN seqnum = 3 THEN value END) as greeting3,
MAX(CASE WHEN seqnum = 4 THEN value END) as greeting4,
MAX(CASE WHEN seqnum = 5 THEN value END) as greeting5,
MAX(CASE WHEN seqnum = 6 THEN value END) as greeting6
FROM (SELECT s.value,
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as seqnum
FROM STRING_SPLIT(t1.Message,'"')
WHERE value LIKE '%.%'
) s
) s;

Note: In practice, this will probably preserve the ordering of the values. However that is not guaranteed -- based on the documentation.

T-SQL Pivot with Custom Column names

Easy way for this is to use group by, sum and case -- like so:

SELECT  UserName,
SUM(CASE WHEN Job_Func = 'DEV' THEN 1 ELSE 0 END) AS Developer,
SUM(CASE WHEN Job_Func = 'NET_ENG' THEN 1 ELSE 0 END) AS NetworkEngineer,
SUM(CASE WHEN Job_Func = 'QA' THEN 1 ELSE 0 END) AS QA,
SUM(CASE WHEN Job_Func = 'SUPERVISOR' THEN 1 ELSE 0 END) AS Supervisor
FROM TABLE_NAME
GROUP BY UserName

If you only want 1 even when a job function is listed more than once you can use MAX instead of SUM

Get custom column name while doing pivot in SQL Server

It is a simple query and you don't need a sub-query or CTE:

just remember Pivot will rename the From table to Pivot Table [e.g. Col] :

select
name,
Col.[1] as amountval1,
Col.[2] as amountval2
from bank
PIVOT (sum(amount) For Val in ([1],[2])) Col

Creating Dynamic Pivot Table Column Names

Your result is correct above however, you will not have your columns sorted by the correct date...

The below would cater for that:

DECLARE
@Cols1 VARCHAR(MAX),
@Cols2 VARCHAR(MAX),
@Query VARCHAR(MAX),
@Period VARCHAR(MAX) = -13 ; --/ Select number of months to view back on (excluding current month) \--

declare @tmptbl table (PeriodDate datetime, col1 varchar(100), col2 varchar(100))
insert into @tmptbl (PeriodDate, col1, col2)

SELECT DISTINCT dPeriodDate,'ISNULL('+ QUOTENAME(CONCAT(DATENAME(MONTH, dPeriodDate),' ',YEAR(dPeriodDate)))+',0) AS' + QUOTENAME(CONCAT(DATENAME(MONTH, dPeriodDate),' ',YEAR(dPeriodDate))) col1
, QUOTENAME(CONCAT(DATENAME(MONTH, dPeriodDate),' ',YEAR(dPeriodDate))) col2
FROM _bvSTTransactionsFull AS S join _etblPeriod p on EOMONTH(s.TxDate) = p.dPeriodDate
WHERE S.Module = 'AR' AND S.TxDate > = DATEADD(MONTH, -13, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0))

SELECT
@Cols1 = STUFF((SELECT ',' + col1
FROM @tmptbl order by PeriodDate
FOR XML PATH (''), TYPE).value('.','NVARCHAR(MAX)'),1,1,'') --/ allows the first SELECT fields to have the ISNULL function and Alias \--
SELECT
@Cols2 = STUFF((SELECT ',' + col2
FROM @tmptbl order by PeriodDate
FOR XML PATH (''), TYPE).value('.','NVARCHAR(MAX)'),1,1,'') --/ becasue of the need for ISNULL above, second @Cols needed for the Pivot (pivot cannot have ISNULL in it) \--

SELECT
@Query =
'SELECT
Item_Code_Desc,
'+@Cols1+'
FROM
(SELECT
CONCAT(ST.Code,'' - '', ST.Description_1) AS Item_Code_Desc,
STT.ActualQuantity AS Qty,
CONCAT(DATENAME(MONTH, STT.TxDate),'' '',YEAR(STT.TxDate)) AS [Period]
FROM
_bvSTTransactionsFull AS STT
INNER JOIN
StkItem AS ST ON STT.AccountLink = ST.StockLink
WHERE
STT.TxDate >= DATEADD(MONTH, '+@Period+', DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0))
AND STT.Module = ''AR'') AS P
PIVOT
(SUM(P.Qty)
FOR P.Period IN ('+@cols2+')
) AS PVT '

PRINT @Query
EXEC (@Query)

I left the changes I made in small caps for you to see the changes...

Dynamic Column Names with Pivot SQL

Your stored procedure looks like it's incomplete or you've changed certain things, but I believe you're looking for something like the following:

DECLARE @ProgramList VARCHAR(MAX);
SELECT @ProgramList = STUFF((SELECT ',' + QUOTENAME(ServerName) FROM [Servers] ORDER BY ServerURL FOR XML PATH ('')), 1, 1, '');

DECLARE @sql VARCHAR(MAX);
SELECT @sql = '
SELECT *
FROM
(
SELECT P.Name,
P.Entity,
P.Field,
S.ServerName
FROM ProjectFields AS P
JOIN [Servers] AS S
ON S.ServerURL = P.ServerURL
) AS P
PIVOT
(
MIN(Field) FOR ServerName IN (' + @ProgramList + ')
) AS PIV
ORDER BY PIV.Name;';

--PRINT @sql;
EXEC sp_executesql @sql;

SQL Server Dynamic Pivot Column Names

DECLARE @cols NVARCHAR (MAX)

SELECT @cols = COALESCE (@cols + ',[' + COLUMN_NAME + ']',
'[' + COLUMN_NAME + ']')
FROM (SELECT DISTINCT COLUMN_NAME,INFORMATION_SCHEMA.COLUMNS.ORDINAL_POSITION O
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'CODES') PV
ORDER BY O

DECLARE @query NVARCHAR(MAX)
SET @query = '
SELECT TOP 0 * FROM
(
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = ''CODES''
) x
PIVOT
(
MIN(COLUMN_NAME)
FOR [COLUMN_NAME] IN (' + @cols + ')
) p

'
EXEC SP_EXECUTESQL @query

MSSQL dynamic pivot column values to column header

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 |

Change column name while using PIVOT SQL Server 2008

Use AS to give a column alias.

SELECT EmployeeID,
[DD14C4C2-FC9E-4A2E-9B96-C6A20A169B2E] AS Name,
[BE8149E2-0806-4D59-8482-58223C2F1735] AS Age,
[23B2C459-3D30-41CA-92AE-7F581F2535D4] AS Salary
FROM EmployeeAttributes PIVOT ( MAX(VALUE) FOR AttributeID IN (
[DD14C4C2-FC9E-4A2E-9B96-C6A20A169B2E],
[BE8149E2-0806-4D59-8482-58223C2F1735],
[23B2C459-3D30-41CA-92AE-7F581F2535D4]) ) P


Related Topics



Leave a reply



Submit