PIVOT/UNPIVOT more than one column
Is there a way to use SQL Pivot/Unpivot to produce the output under Converted below from the table Original?

sql
add a comment |
Is there a way to use SQL Pivot/Unpivot to produce the output under Converted below from the table Original?

sql
2
Please show your code attempt.
– Dale Burrell
Jan 2 at 4:05
add a comment |
Is there a way to use SQL Pivot/Unpivot to produce the output under Converted below from the table Original?

sql
Is there a way to use SQL Pivot/Unpivot to produce the output under Converted below from the table Original?

sql
sql
edited Jan 4 at 16:02
Andrea
7,731144753
7,731144753
asked Jan 2 at 4:01
VTISCHUKVTISCHUK
174
174
2
Please show your code attempt.
– Dale Burrell
Jan 2 at 4:05
add a comment |
2
Please show your code attempt.
– Dale Burrell
Jan 2 at 4:05
2
2
Please show your code attempt.
– Dale Burrell
Jan 2 at 4:05
Please show your code attempt.
– Dale Burrell
Jan 2 at 4:05
add a comment |
2 Answers
2
active
oldest
votes
No, there is no variation of PIVOT/UNPIVOT that will let you create that first row in your "converted" output, with the id in one column and the values of type for each of the other columns.
That's going to require some custom select to create the first row, and then UNION with an UNPIVOT to create the rest of the rows.
Since no aggregation is being performed, I don't know why you want to do this in SQL. Personally I would do this in the presentation layer.
add a comment |
You can achieve the "converted" layout with dynamic sql, but be aware of performance and security problems of this approach.
Moreover as said by Tab Alleman in his answer this is clearly a work for the presentation layer.
If you still want to do this in SQL Server, here is a possible solution:
CREATE TABLE [dbo].[Test] (
[id] int
,[type] varchar(50)
,NBR varchar(50)
,c1_pos int
,c1_neg int
,c2_pos int
,c2_neg int )
INSERT INTO [dbo].[Test]
values
(8375, 'Type #1', 'P #1', 1, 0, 0, 0)
,(8375, 'Type #2', 'P #2', 0, 1, 0, 0)
,(8375, 'Type #3', 'P #1', 0, 1, 0, 0)
,(8375, 'Type #4', 'P #1', 1, 0, 0, 0)
,(8375, 'Type #5', 'P #1', 0, 0, 0, 0)
--this variable holds the value that will become the header of the first column
declare @first_column_header nvarchar(10)
--this variable holds all the dates that will become column names
declare @headers nvarchar(max)=''
--this variable contains the TSQL dinamically generated
declare @sql nvarchar(max)=''
SELECT @first_column_header = max(id) FROM [dbo].[Test] group by [id]
select @headers = @headers + ', ' + QUOTENAME([type]) from [dbo].[Test]
set @headers = RIGHT(@headers, len(@headers) - 2)
set @sql = @sql + 'select piv.col as ' + QUOTENAME(@first_column_header) + ', ' + @headers + ' '
set @sql = @sql + 'from '
set @sql = @sql + '( '
set @sql = @sql + ' select [type], col, val, ord '
set @sql = @sql + ' from [dbo].[Test] '
set @sql = @sql + ' CROSS APPLY ('
set @sql = @sql + ' VALUES (''NBR'' , cast(NBR as varchar(10)) , 1), '
set @sql = @sql + ' (''c1_pos'' , cast(c1_pos as varchar(10)) , 2), '
set @sql = @sql + ' (''c1_neg'' , cast(c1_neg as varchar(10)) , 3), '
set @sql = @sql + ' (''c2_pos'' , cast(c2_pos as varchar(10)) , 4), '
set @sql = @sql + ' (''c2_neg'' , cast(c2_neg as varchar(10)) , 5) '
set @sql = @sql + ' )CS (col, val, ord) '
set @sql = @sql + ') src '
set @sql = @sql + 'pivot ( max(val) for [type] in (' + @headers + ') ) piv '
set @sql = @sql + 'order by ord'
exec(@sql)
Result:

add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54001053%2fpivot-unpivot-more-than-one-column%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
No, there is no variation of PIVOT/UNPIVOT that will let you create that first row in your "converted" output, with the id in one column and the values of type for each of the other columns.
That's going to require some custom select to create the first row, and then UNION with an UNPIVOT to create the rest of the rows.
Since no aggregation is being performed, I don't know why you want to do this in SQL. Personally I would do this in the presentation layer.
add a comment |
No, there is no variation of PIVOT/UNPIVOT that will let you create that first row in your "converted" output, with the id in one column and the values of type for each of the other columns.
That's going to require some custom select to create the first row, and then UNION with an UNPIVOT to create the rest of the rows.
Since no aggregation is being performed, I don't know why you want to do this in SQL. Personally I would do this in the presentation layer.
add a comment |
No, there is no variation of PIVOT/UNPIVOT that will let you create that first row in your "converted" output, with the id in one column and the values of type for each of the other columns.
That's going to require some custom select to create the first row, and then UNION with an UNPIVOT to create the rest of the rows.
Since no aggregation is being performed, I don't know why you want to do this in SQL. Personally I would do this in the presentation layer.
No, there is no variation of PIVOT/UNPIVOT that will let you create that first row in your "converted" output, with the id in one column and the values of type for each of the other columns.
That's going to require some custom select to create the first row, and then UNION with an UNPIVOT to create the rest of the rows.
Since no aggregation is being performed, I don't know why you want to do this in SQL. Personally I would do this in the presentation layer.
answered Jan 2 at 14:54
Tab AllemanTab Alleman
26.8k52441
26.8k52441
add a comment |
add a comment |
You can achieve the "converted" layout with dynamic sql, but be aware of performance and security problems of this approach.
Moreover as said by Tab Alleman in his answer this is clearly a work for the presentation layer.
If you still want to do this in SQL Server, here is a possible solution:
CREATE TABLE [dbo].[Test] (
[id] int
,[type] varchar(50)
,NBR varchar(50)
,c1_pos int
,c1_neg int
,c2_pos int
,c2_neg int )
INSERT INTO [dbo].[Test]
values
(8375, 'Type #1', 'P #1', 1, 0, 0, 0)
,(8375, 'Type #2', 'P #2', 0, 1, 0, 0)
,(8375, 'Type #3', 'P #1', 0, 1, 0, 0)
,(8375, 'Type #4', 'P #1', 1, 0, 0, 0)
,(8375, 'Type #5', 'P #1', 0, 0, 0, 0)
--this variable holds the value that will become the header of the first column
declare @first_column_header nvarchar(10)
--this variable holds all the dates that will become column names
declare @headers nvarchar(max)=''
--this variable contains the TSQL dinamically generated
declare @sql nvarchar(max)=''
SELECT @first_column_header = max(id) FROM [dbo].[Test] group by [id]
select @headers = @headers + ', ' + QUOTENAME([type]) from [dbo].[Test]
set @headers = RIGHT(@headers, len(@headers) - 2)
set @sql = @sql + 'select piv.col as ' + QUOTENAME(@first_column_header) + ', ' + @headers + ' '
set @sql = @sql + 'from '
set @sql = @sql + '( '
set @sql = @sql + ' select [type], col, val, ord '
set @sql = @sql + ' from [dbo].[Test] '
set @sql = @sql + ' CROSS APPLY ('
set @sql = @sql + ' VALUES (''NBR'' , cast(NBR as varchar(10)) , 1), '
set @sql = @sql + ' (''c1_pos'' , cast(c1_pos as varchar(10)) , 2), '
set @sql = @sql + ' (''c1_neg'' , cast(c1_neg as varchar(10)) , 3), '
set @sql = @sql + ' (''c2_pos'' , cast(c2_pos as varchar(10)) , 4), '
set @sql = @sql + ' (''c2_neg'' , cast(c2_neg as varchar(10)) , 5) '
set @sql = @sql + ' )CS (col, val, ord) '
set @sql = @sql + ') src '
set @sql = @sql + 'pivot ( max(val) for [type] in (' + @headers + ') ) piv '
set @sql = @sql + 'order by ord'
exec(@sql)
Result:

add a comment |
You can achieve the "converted" layout with dynamic sql, but be aware of performance and security problems of this approach.
Moreover as said by Tab Alleman in his answer this is clearly a work for the presentation layer.
If you still want to do this in SQL Server, here is a possible solution:
CREATE TABLE [dbo].[Test] (
[id] int
,[type] varchar(50)
,NBR varchar(50)
,c1_pos int
,c1_neg int
,c2_pos int
,c2_neg int )
INSERT INTO [dbo].[Test]
values
(8375, 'Type #1', 'P #1', 1, 0, 0, 0)
,(8375, 'Type #2', 'P #2', 0, 1, 0, 0)
,(8375, 'Type #3', 'P #1', 0, 1, 0, 0)
,(8375, 'Type #4', 'P #1', 1, 0, 0, 0)
,(8375, 'Type #5', 'P #1', 0, 0, 0, 0)
--this variable holds the value that will become the header of the first column
declare @first_column_header nvarchar(10)
--this variable holds all the dates that will become column names
declare @headers nvarchar(max)=''
--this variable contains the TSQL dinamically generated
declare @sql nvarchar(max)=''
SELECT @first_column_header = max(id) FROM [dbo].[Test] group by [id]
select @headers = @headers + ', ' + QUOTENAME([type]) from [dbo].[Test]
set @headers = RIGHT(@headers, len(@headers) - 2)
set @sql = @sql + 'select piv.col as ' + QUOTENAME(@first_column_header) + ', ' + @headers + ' '
set @sql = @sql + 'from '
set @sql = @sql + '( '
set @sql = @sql + ' select [type], col, val, ord '
set @sql = @sql + ' from [dbo].[Test] '
set @sql = @sql + ' CROSS APPLY ('
set @sql = @sql + ' VALUES (''NBR'' , cast(NBR as varchar(10)) , 1), '
set @sql = @sql + ' (''c1_pos'' , cast(c1_pos as varchar(10)) , 2), '
set @sql = @sql + ' (''c1_neg'' , cast(c1_neg as varchar(10)) , 3), '
set @sql = @sql + ' (''c2_pos'' , cast(c2_pos as varchar(10)) , 4), '
set @sql = @sql + ' (''c2_neg'' , cast(c2_neg as varchar(10)) , 5) '
set @sql = @sql + ' )CS (col, val, ord) '
set @sql = @sql + ') src '
set @sql = @sql + 'pivot ( max(val) for [type] in (' + @headers + ') ) piv '
set @sql = @sql + 'order by ord'
exec(@sql)
Result:

add a comment |
You can achieve the "converted" layout with dynamic sql, but be aware of performance and security problems of this approach.
Moreover as said by Tab Alleman in his answer this is clearly a work for the presentation layer.
If you still want to do this in SQL Server, here is a possible solution:
CREATE TABLE [dbo].[Test] (
[id] int
,[type] varchar(50)
,NBR varchar(50)
,c1_pos int
,c1_neg int
,c2_pos int
,c2_neg int )
INSERT INTO [dbo].[Test]
values
(8375, 'Type #1', 'P #1', 1, 0, 0, 0)
,(8375, 'Type #2', 'P #2', 0, 1, 0, 0)
,(8375, 'Type #3', 'P #1', 0, 1, 0, 0)
,(8375, 'Type #4', 'P #1', 1, 0, 0, 0)
,(8375, 'Type #5', 'P #1', 0, 0, 0, 0)
--this variable holds the value that will become the header of the first column
declare @first_column_header nvarchar(10)
--this variable holds all the dates that will become column names
declare @headers nvarchar(max)=''
--this variable contains the TSQL dinamically generated
declare @sql nvarchar(max)=''
SELECT @first_column_header = max(id) FROM [dbo].[Test] group by [id]
select @headers = @headers + ', ' + QUOTENAME([type]) from [dbo].[Test]
set @headers = RIGHT(@headers, len(@headers) - 2)
set @sql = @sql + 'select piv.col as ' + QUOTENAME(@first_column_header) + ', ' + @headers + ' '
set @sql = @sql + 'from '
set @sql = @sql + '( '
set @sql = @sql + ' select [type], col, val, ord '
set @sql = @sql + ' from [dbo].[Test] '
set @sql = @sql + ' CROSS APPLY ('
set @sql = @sql + ' VALUES (''NBR'' , cast(NBR as varchar(10)) , 1), '
set @sql = @sql + ' (''c1_pos'' , cast(c1_pos as varchar(10)) , 2), '
set @sql = @sql + ' (''c1_neg'' , cast(c1_neg as varchar(10)) , 3), '
set @sql = @sql + ' (''c2_pos'' , cast(c2_pos as varchar(10)) , 4), '
set @sql = @sql + ' (''c2_neg'' , cast(c2_neg as varchar(10)) , 5) '
set @sql = @sql + ' )CS (col, val, ord) '
set @sql = @sql + ') src '
set @sql = @sql + 'pivot ( max(val) for [type] in (' + @headers + ') ) piv '
set @sql = @sql + 'order by ord'
exec(@sql)
Result:

You can achieve the "converted" layout with dynamic sql, but be aware of performance and security problems of this approach.
Moreover as said by Tab Alleman in his answer this is clearly a work for the presentation layer.
If you still want to do this in SQL Server, here is a possible solution:
CREATE TABLE [dbo].[Test] (
[id] int
,[type] varchar(50)
,NBR varchar(50)
,c1_pos int
,c1_neg int
,c2_pos int
,c2_neg int )
INSERT INTO [dbo].[Test]
values
(8375, 'Type #1', 'P #1', 1, 0, 0, 0)
,(8375, 'Type #2', 'P #2', 0, 1, 0, 0)
,(8375, 'Type #3', 'P #1', 0, 1, 0, 0)
,(8375, 'Type #4', 'P #1', 1, 0, 0, 0)
,(8375, 'Type #5', 'P #1', 0, 0, 0, 0)
--this variable holds the value that will become the header of the first column
declare @first_column_header nvarchar(10)
--this variable holds all the dates that will become column names
declare @headers nvarchar(max)=''
--this variable contains the TSQL dinamically generated
declare @sql nvarchar(max)=''
SELECT @first_column_header = max(id) FROM [dbo].[Test] group by [id]
select @headers = @headers + ', ' + QUOTENAME([type]) from [dbo].[Test]
set @headers = RIGHT(@headers, len(@headers) - 2)
set @sql = @sql + 'select piv.col as ' + QUOTENAME(@first_column_header) + ', ' + @headers + ' '
set @sql = @sql + 'from '
set @sql = @sql + '( '
set @sql = @sql + ' select [type], col, val, ord '
set @sql = @sql + ' from [dbo].[Test] '
set @sql = @sql + ' CROSS APPLY ('
set @sql = @sql + ' VALUES (''NBR'' , cast(NBR as varchar(10)) , 1), '
set @sql = @sql + ' (''c1_pos'' , cast(c1_pos as varchar(10)) , 2), '
set @sql = @sql + ' (''c1_neg'' , cast(c1_neg as varchar(10)) , 3), '
set @sql = @sql + ' (''c2_pos'' , cast(c2_pos as varchar(10)) , 4), '
set @sql = @sql + ' (''c2_neg'' , cast(c2_neg as varchar(10)) , 5) '
set @sql = @sql + ' )CS (col, val, ord) '
set @sql = @sql + ') src '
set @sql = @sql + 'pivot ( max(val) for [type] in (' + @headers + ') ) piv '
set @sql = @sql + 'order by ord'
exec(@sql)
Result:

answered Jan 4 at 15:58
AndreaAndrea
7,731144753
7,731144753
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54001053%2fpivot-unpivot-more-than-one-column%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
Please show your code attempt.
– Dale Burrell
Jan 2 at 4:05