PIVOT other items in SQL - sql

I have a table that I need to PIVOT its columns but I'm not sure if there's an easy way to do it.
Here's the portion of my table:
Category | Item | Total
Food | 1 | $500
Food | 2 | $1,000
Food | 3 | $750
Pivot result (which is correct):
Category | item_1 | item_2 | item_3
Food | $500 | $1,000 | $750
my code:
SELECT category,
[1] as item_1,
[2] as item_2,
[3] as item_3
FROM (
SELECT category, item, SUM(item_total) as item_total FROM (
SELECT category, item, total
FROM tbl_product
where category = 'Food'
) prod
GROUP BY category, item) sourcetable
PIVOT
(
AVG(item_total)
FOR item IN ([1],[2],[3])
) as PivotTable;
However, I do have more than 50 items. I would like to group these items into columns.
Example: items 7-20 should be in misc_1 column, 21-50 as misc_2 column
so it would look like this:
Category | item_1 | item_2 | item_3 | misc_1 | misc_2
Food | $500 | $1,000 | $750 | $8,000 | $5,700
As much as possible, I don't like to put every single items in the "item IN ([1],...)"
Please let me know if it's possible to combine those group items into single column.
Thank you.

You have to do the same query but dynamically, something like this:
DECLARE #cols AS NVARCHAR(MAX);
DECLARE #colnames AS NVARCHAR(MAX);
DECLARE #query AS NVARCHAR(MAX);
SELECT #cols = STUFF((SELECT distinct ',' +
QUOTENAME(item)
FROM tbl_product AS t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
SELECT #colnames = STUFF((SELECT distinct ',' +
QUOTENAME(item) + 'AS' +
CASE WHEN rn < 7 THEN QUOTENAME('Item_' + CAST(item AS NVARCHAR(5)))
ELSE QUOTENAME('Misc_' + CAST(item AS NVARCHAR(5))) END
FROM (SELECT ROW_NUMBER() OVER(ORDER BY item) AS rn, item FROM tbl_product) AS t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
SELECT #query = 'SELECT category, '+ #colnames + '
FROM (
SELECT category, item, SUM(total) as item_total
FROM (
SELECT category, item, total
FROM tbl_product
) prod
GROUP BY category, item) sourcetable
PIVOT
(
AVG(item_total)
FOR item IN (' + #cols + ')' +
') p';
execute(#query);
Note that:
For the column names, I used:
SELECT #colnames = STUFF((SELECT distinct ',' +
QUOTENAME(item) + 'AS' +
CASE WHEN rn < 7 THEN QUOTENAME('Item_' + CAST(item AS NVARCHAR(5)))
ELSE QUOTENAME('Misc_' + CAST(item AS NVARCHAR(5))) END
FROM (SELECT ROW_NUMBER() OVER(ORDER BY item) AS rn, item FROM tbl_product) AS t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
To select those the first 7 items with the names item_, whereas the rest of the items with the names Misc_. You can edit in this statement to customize how you would like to display the items' names.

Related

SQL How to pivot two columns of data into different columns?

This is the table I have:
| Scheme Code | MonthYear | Revenue | Revenue2 |
|-------------|-----------|---------|----------|
| 18VDA | 2018.1 | 100 | 50 |
| 18VDA | 2018.2 | 200 | 100 |
| 18VDA | 2018.3 | 200 | 150 |
and I want to pivot it to like this:
| Scheme Code | 2018.1 A | 2018.2 A | 2018.3 A | 2018.1 B | 2018.2 B | 2018.3 B |
|-------------|----------|----------|----------|----------|----------|----------|
| 18VDA | 100 | 200 | 200 | 50 | 100 | 150 |
How do I do it so that it pivots in MonthYear, but it duplicates it for both Revenue and Revenue2?
Thanks
EDIT: Messed up the output table I was hoping for! I've edited the actual output table I want to see!
EDIT 2:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
Select #cols = STUFF((SELECT ',' + QUOTENAME([MonthYear])
from tableA
group by [MonthYear]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT *
FROM ( SELECT [Scheme Code], MonthYear ,[Revenue]
FROM TableA
) a
PIVOT(sum(Revenue) for MonthYear in (' + #cols + ')
) as RevenueMonth
ORDER BY [Scheme Code]'
execute(#query);
This code I wrote will do it for just one column, and I get the output like this:
| Scheme Code | 2018.1 | 2018.2 | 2018.3 |
|-------------|--------|--------|--------|
| 18VDA | 100 | 200 | 200 |
My suggestion always is to try to write your query as a hard-coded or static version first before diving into dynamic SQL. This let's you get the final result you want with a smaller subset of data and you can verify that you have the logic correct.
I would tackle this by performing an UNPIVOT of the two Revenue columns first, then look at applying the PIVOT function. To UNPIVOT you can use either the UNPIVOT function or you can use CROSS APPLY with a UNION ALL to convert your two Revenue columns into a single column. A static version of the query would be similar to this:
select *
from
(
select
t.[Scheme Code],
new_colname = concat(t.[MonthYear], ' ', r.colname),
r.colvalue
from yourtable t
cross apply
(
select 'A', Revenue union all
select 'B', Revenue2
) r (colname, colvalue)
) d
pivot
(
sum(colvalue)
for new_colname in ([2018.1 A], [2018.2 A], [2018.3 A], [2018.1 B], [2018.2 B], [2018.3 B])
) p;
You'll notice that in the CROSS APPLY I added a column with the A or B that I use to identify either the Revenue or Revenue2 columns. This is then used to create the new column names for the PIVOT.
This should generate the result you want. Now to do this dynamically, you just need to convert the SQL to dynamic code. You can use the following to get the result:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
Select #cols = STUFF((SELECT ',' + QUOTENAME(concat([MonthYear], x.col))
from yourtable
cross join (select col = ' A' union all select ' B') x
group by [MonthYear], x.col
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT *
FROM
(
select
t.[Scheme Code],
new_colname = concat(t.[MonthYear], '' '', r.colname),
r.colvalue
from yourtable t
cross apply
(
select ''A'', Revenue union all
select ''B'', Revenue2
) r (colname, colvalue)
) a
PIVOT
(
sum(colvalue) for new_colname in (' + #cols + ')
) as x
ORDER BY [Scheme Code]';
exec sp_executesql #query;
Both of these should generate the same results (dbfiddle demo)
Do it with CASE and dynamic sql.
DECLARE #colsA AS NVARCHAR(MAX),
#colsB AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #colsA = (SELECT ', sum(case [MonthYear] when ''' + [MonthYear] + ''' then Revenue end)' + QUOTENAME([MonthYear] + ' A')
from tableA
group by [MonthYear]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),
#colsB = (SELECT ', sum(case [MonthYear] when ''' + [MonthYear] + ''' then Revenue2 end)' + QUOTENAME([MonthYear] + ' B')
from tableA
group by [MonthYear]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)');
Set #query = 'select [Scheme Code]' + #colsA + #colsB + ' from TableA group by [Scheme Code] order by [Scheme Code];';
print #query;

How to group mean values of a column after pivoting in SQL Server

I have the following lines of SQL code which are part of a stored procedure:
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME([vw_Imported_Files].RF_FileName)
FROM [dbo].[vw_Imported_Files] with(nolock)
WHERE [vw_Imported_Files].RF_GUID_ID = #sGUID
AND [vw_Imported_Files].RF_IsEnabled = 1
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #query2 = 'SELECT ROUND(AVG(CAST(RD_Axis AS FLOAT)),3) AS RD_Axis
,' + #cols + ' FROM
(SELECT ROW_NUMBER() OVER (PARTITION BY DenseRank ORDER BY (SELECT NULL))
AS RowNumber, rd.* FROM
(SELECT DENSE_RANK() OVER (ORDER BY rd.RD_RF_ID) AS DenseRank
,rd.RD_Axis AS RD_Axis
,rd.DN_Values AS DN_Values
,rd.RF_FileName AS RF_FileName
FROM #TEMP rd
WHERE rd.RD_GUID_ID = ' + #sGUID + '
AND rd.RD_IsEnabled = 1
) rd
) rn
pivot
(
max(DN_Values)
for RF_FileName in (' + #cols + ')
) p
GROUP BY RD_Axis, ' + #cols + ' '
execute (#query2)
Actually, this query (#query2) results as shown in the following table.
---------------------------------------------------------------
| 0 | NULL | NULL | 0,996573652935408|
| 0 | NULL | 1,00053003751428 | NULL |
| 0 | 0,999843071844672 | NULL | NULL |
| 0,052 | NULL | NULL | 0,992999630825293|
| 0,052 | 1,02368347072563 | NULL | NULL |
| 0,053 | NULL | 0,992674427713489 | NULL |
| 0,104 | NULL | NULL | 0,998690236570867|
| 0,104 | NULL | 0,996645964692132 | NULL |
| 0,105 | 0,989815140503533 | NULL | NULL |
----------------------------------------------------------------------------
What I want to do, is to clear all the NULL values by grouping the Average of the RD_Axis values that have the same DenseRank value. In the current instance, the DenseRank increases every 3 rows. So, the outcome that I want has to look like as depicted in the next table.
----------------------------------------------------------------------------
| 0 | 0,999843071844672 | 1,00053003751428 | 0,996573652935408|
| 0,052 | 1,02368347072563 | 0,992674427713489 | 0,992999630825293|
| 0,104 | 0,989815140503533 | 0,996645964692132 | 0,998690236570867|
----------------------------------------------------------------------------
I hope to find my inquiry clear. Could you please help me to figure out how to transform the above SQL code in order for me to get the desirable result?
You might need to create a new column variable that gets the MAX(dynamicColumn) value for your outer select.. that way you can remove the GROUP BY at the end.
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME([vw_Imported_Files].RF_FileName)
FROM [dbo].[vw_Imported_Files] with(nolock)
WHERE [vw_Imported_Files].RF_GUID_ID = #sGUID
AND [vw_Imported_Files].RF_IsEnabled = 1
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #maxCols = STUFF((SELECT distinct ', MAX(' + QUOTENAME([vw_Imported_Files].RF_FileName) + ') AS ' + QUOTENAME([vw_Imported_Files].RF_FileName)
FROM [dbo].[vw_Imported_Files] with(nolock)
WHERE [vw_Imported_Files].RF_GUID_ID = #sGUID
AND [vw_Imported_Files].RF_IsEnabled = 1
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #query2 = '
SELECT ROUND(AVG(CAST(RD_Axis AS FLOAT)),3) AS RD_Axis
,' + #maxCols + '
FROM
(SELECT ROW_NUMBER() OVER (PARTITION BY DenseRank ORDER BY (SELECT NULL))
AS RowNumber, rd.*
FROM (SELECT DENSE_RANK() OVER (ORDER BY rd.RD_RF_ID) AS DenseRank
,rd.RD_Axis AS RD_Axis
,rd.DN_Values AS DN_Values
,rd.RF_FileName AS RF_FileName
FROM #TEMP rd
WHERE rd.RD_GUID_ID = ' + #sGUID + ' AND rd.RD_IsEnabled = 1
) rd
) rn
pivot
(
max(DN_Values)
for RF_FileName in (' + #cols + ')
) p
GROUP BY DenseRank'
execute (#query2)
This can probably be done without using PIVOT and be a lot cleaner by using aggregates with CASE expressions
Actually I got the result that I was looking for with the following code.
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME([vw_Imported_Files].RF_FileName)
FROM [dbo].[vw_Imported_Files] with(nolock)
WHERE [vw_Imported_Files].RF_GUID_ID = #sGUID and [vw_Imported_Files].RF_IsEnabled = 1
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #maxCols = STUFF((SELECT distinct ', MAX(' + QUOTENAME([vw_Imported_Files].RF_FileName) + ') AS ' + QUOTENAME([vw_Imported_Files].RF_FileName)
FROM [dbo].[vw_Imported_Files] with(nolock)
WHERE [vw_Imported_Files].RF_GUID_ID = #sGUID AND [vw_Imported_Files].RF_IsEnabled = 1
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #query2 = '
SELECT ' + #maxCols + '
FROM
(SELECT ROW_NUMBER() OVER (PARTITION BY DenseRank ORDER BY (SELECT NULL))
AS RowNumber, rd.*
FROM (SELECT DENSE_RANK() OVER (ORDER BY rd.RD_RF_ID) AS DenseRank
,rd.RD_Axis AS RD_Axis
,rd.DN_Values AS DN_Values
,rd.RF_FileName AS RF_FileName
FROM #TEMP rd
WHERE rd.RD_GUID_ID = ' + #sGUID + ' AND rd.RD_IsEnabled = 1
) rd
) rn
pivot
(
max(DN_Values)
for RF_FileName in (' + #cols + ')
) p
GROUP BY RowNumber ORDER BY RowNumber'
execute (#query2)
At first I generated the outcome that I wanted (#query2) and then I got the average of the RD_Axis values with another query (both ordered by Rownumber asc). Then I linked them with a UNION ALL statement. Btw, thanks for the fresh perspective on my issue because I had been stuck for hours.

Dynamic pivot with similar column names

I'm looking for a way to pivot a varying amount of rows to columns in sql server 2008 R2. I created the data column RANK in the query because, ultimately I want the pivoted column names to be labeled the value in the RANK column. Then, if somehow I can STUFF the other 3 field values together into one field I would be able to iterate over the row in my backend lang and split the field results appropriately.
Here is the current data set:
And I would like the end result of the pivot to produce a result like this:
I haven't found anything about being able to pivot in this "dynamic" way. Any help would be much appreciated.
As I mentioned above, you need to distinguish each of your Rank values. You've said that this is a calculated value that you can add a number to the end of each one. Once you've added that number, then you still need to pivot it.
The easiest way to first see this would be to write a hard-coded version of the query first.
Sample Data:
create table yourdata
(
id int,
code varchar(50),
created datetime,
[rank] varchar(50)
);
insert into yourdata
select 285856, 'J7609', '2015-01-19', 'Principle' union all
select 285856, 'J7613', '2015-01-19', 'Other' union all
select 285856, 'J0456', '2015-01-19', 'Other' union all
select 285856, 'J0694', '2015-01-19', 'Other' union all
select 285856, 'J1885', '2015-01-19', 'Other' union all
select 285856, 'J2060', '2015-01-19', 'Other' union all
select 285856, 'J2930', '2015-01-19', 'Other';
Static Query:
select Principle_1, Other_1,
Other_2, Other_3, Other_4,
Other_5, Other_6
from
(
-- using row_number to get unique id for each rank
select
data = cast(id as varchar(10)) +' | '+ code +' | '+ convert(varchar(10), created, 112),
[rank] = [rank] + '_' +cast(row_number() over(partition by id, [rank]
order by id) as varchar(10))
from yourdata
) d
pivot
(
max(data)
for [rank] in (Principle_1, Other_1, Other_2, Other_3, Other_4,
Other_5, Other_6)
) p;
Now to do this dynamic, you will create a sql string with the column names and then execute that string:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME([rank] + '_' +cast(rn as varchar(10)))
from
(
select [rank],
rn = row_number() over(partition by id, [rank]
order by id)
from yourdata
) d
group by [rank], rn
order by rn, [rank] desc
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT ' + #cols + '
from
(
select
data = cast(id as varchar(10)) +'' | ''+ code +'' | ''+ convert(varchar(10), created, 112),
[rank] = [rank] + ''_'' +cast(row_number() over(partition by id, [rank]
order by id) as varchar(10))
from yourdata
) x
pivot
(
max(data)
for [rank] in (' + #cols + ')
) p '
exec sp_executesql #query;
This gets you a result:
+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+
| Principle_1 | Other_1 | Other_2 | Other_3 | Other_4 | Other_5 | Other_6 |
+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+
| 285856 | J7609 | 20150119 | 285856 | J7613 | 20150119 | 285856 | J0456 | 20150119 | 285856 | J0694 | 20150119 | 285856 | J1885 | 20150119 | 285856 | J2060 | 20150119 | 285856 | J2930 | 20150119 |
+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+

Format Jagged data gained from dynamic pivot

I need to format and extract some data from a database. While I can extract the data successfully I am struggling with the jagged nature of it.
What I have is the following:
create table temp
(
QuestionID INT,
AnswerID INT,
AnswerValue NVARCHAR(50)
)
insert into temp values (1, 1, 'Ans C')
insert into temp values (1, 2, 'Ans B')
insert into temp values (1, 3, 'Ans A')
insert into temp values (2, 4, 'Ans D')
insert into temp values (2, 5, 'Ans E')
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.AnswerID)
FROM temp c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT QuestionID, ' + #cols + ' from
(
select QuestionID
, AnswerValue
, AnswerID
from temp
) x
pivot
(
max(AnswerValue)
for AnswerID in (' + #cols + ')
) p '
execute(#query)
drop table temp
Executed this produces
+------------+-------+-------+-------+-------+-------+
| QuestionID | 1 | 2 | 3 | 4 | 5 |
+------------+-------+-------+-------+-------+-------+
| 1 | Ans C | Ans B | Ans A | NULL | NULL |
| 2 | NULL | NULL | NULL | Ans D | Ans E |
+------------+-------+-------+-------+-------+-------+
I just need to format it like this
+------------+-------+-------+-------+
| QuestionID | Q1 | Q2 | Q3 |
+------------+-------+-------+-------+
| 1 | Ans C | Ans B | Ans A |
| 2 | NULL | Ans D | Ans E |
+------------+-------+-------+-------+
Note due to restrictions this needs to be done in SQL rather than an advanced language such as c#.
A few things are wrong with the code. First, you are creating your column list using the AnswerID so the data is being split across multiple columns instead of the Answer for each question.
In order to fix this, you'll want to use a windowing function like row_number() to create a sequence for each question/answer combination.
When creating your dynamic columns change the code to be:
SET #cols = STUFF((SELECT ',' + QUOTENAME('Q'+cast(rn as varchar(10)))
FROM
(
SELECT rn = row_number() over(partition by QuestionID
order by AnswerID)
FROM temp
) c
group by rn
order by rn
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
This will use row_number() and will create the column names based on the QuestionID. Then you'll include the row_number() in your subquery making your code:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SET #cols = STUFF((SELECT ',' + QUOTENAME('Q'+cast(rn as varchar(10)))
FROM
(
SELECT rn = row_number() over(partition by QuestionID
order by AnswerID)
FROM temp
) c
group by rn
order by rn
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT QuestionID, ' + #cols + '
from
(
select QuestionID
, AnswerValue
, col = ''Q''+ cast(row_number() over(partition by QuestionID
order by AnswerID) as varchar(10))
from temp
) x
pivot
(
max(AnswerValue)
for col in (' + #cols + ')
) p '
exec sp_executesql #query;
See SQL Fiddle with Demo. This gives a result:
| QUESTIONID | Q1 | Q2 | Q3 |
|------------|-------|-------|--------|
| 1 | Ans C | Ans B | Ans A |
| 2 | Ans D | Ans E | (null) |
You can use this part of code:
SELECT 'A' + CAST(ROW_NUMBER() OVER(PARTITION BY QuestionID ORDER BY Answer) AS VARCHAR(10)) AS cName
FROM tblAnswers
in order to generate the column names required. The above gives you sth like:
cName
-----
A1
A2
A3
A1
A2
You can subsequently use the above in your dynamic pivot to obtain the desired result:
DECLARE #cols AS NVARCHAR(MAX), #query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(a.cName)
FROM (
SELECT 'A' + CAST(ROW_NUMBER() OVER(PARTITION BY QuestionID ORDER BY Answer) AS VARCHAR(10)) AS cName
FROM tblAnswers
) a
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'')
set #query = 'SELECT Question, ' + #cols + ' ' +
'FROM (
SELECT q.Question, a.Answer,
''A'' + CAST(ROW_NUMBER() OVER(PARTITION BY a.QuestionID ORDER BY Answer) AS VARCHAR(10)) AS cName
FROM tblAnswers AS a
INNER JOIN tblQuestions AS q ON a.QuestionID = q.QuestionID
) t
PIVOT
(
MAX(t.Answer)
FOR cName in (' + #cols + ')
) Pvt '
execute(#query)
Output from above looks like:
Question A1 A2 A3
-----------------------------------
Q1 Answer1 Answer2 Answer3
Q2 Answer4 Answer5 NULL
SQL Fiddle demo here

How can I return several text fields with the same ID number in one row in SQL server?

I have table:
ID Note
1 1 aaa
2 1 bbb
3 1 ccc
4 2 ddd
5 2 eee
6 2 fff
I need to return it as:
ID Note1 Note2 Note3
1 1 aaa bbb ccc
2 2 ddd eee fff
Thank you!
You can use the PIVOT function for this type of query. If you have a known number of columns, then you can hard-code the values:
select *
from
(
select id, note,
'Note' +
cast(row_number() over(partition by id order by id) as varchar(10)) col
from yourtable
) x
pivot
(
max(note)
for col in ([Note1], [Note2], [Note3])
) p
See SQL Fiddle with Demo
If you are going to have an unknown number of notes that you want to turn into columns, then you can use dynamic sql:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ','
+ QUOTENAME('Note' +
cast(row_number() over(partition by id order by id) as varchar(10)))
from yourtable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT id,' + #cols + ' from
(
select id, note,
''Note'' +
cast(row_number() over(partition by id order by id) as varchar(10)) col
from yourtable
) x
pivot
(
max(note)
for col in (' + #cols + ')
) p '
execute(#query)
See SQL Fiddle with Demo
Both will produce the same results.
| ID | NOTE1 | NOTE2 | NOTE3 |
------------------------------
| 1 | aaa | bbb | ccc |
| 2 | ddd | eee | fff |
Or if you do not want to use the PIVOT function, then you can use an aggregate function with a CASE statement:
select id,
max(case when rn = 1 then note else '' end) Note1,
max(case when rn = 2 then note else '' end) Note2,
max(case when rn = 3 then note else '' end) Note3
from
(
select id, note,
row_number() over(partition by id order by id) rn
from yourtable
) src
group by id
See SQL Fiddle with Demo