I am trying to get a handle on manipulating table data into more visually appealing formats for output. This could be part of the problem as what I want may be intended for separate reporting software.
I have a table that looks like this
teacher student
----------------------
teacher1 Bob
teacher1 Jim
teacher2 Sam
teacher3 Bill
teacher3 John
teacher3 Eric
I want a table that looks something like this:
teacher1 teacher2 teacher3
---------------------------------
Bob Sam Bill
Jim null John
null null Eric
So I tried stuffing all the teacher names in a variable and then using a Pivot
but since I have to choose an aggregate I can only get the Max
or Min
student like this:
DECLARE @teacherList AS VARCHAR(max)
SELECT @teacherList = Stuff((SELECT DISTINCT',[' + teacher + ']'
FROM myTable
FOR xml path('')), 1, 1, '')
DECLARE @dynamic_pivot_query AS VARCHAR(max)
SET @dynamic_pivot_query = 'select' + @teacherList +
'from
(
SELECT [teacher],[student]
FROM [dbo].[myTable]
) as S
Pivot
(
MIN([student])
FOR teacher IN (' + @teacherList + ')
) as P
'
EXEC(@dynamic_pivot_query)
The result of this is:
teacher1 teacher2 teacher3
---------------------------------
Bob Sam Bill
Assuming the following:
Is there a way to do this?
No.
SQL Server requires static typing. There is no way to create a dynamic number of columns or dynamic column types (except for sql_variant).
Therefore your dynamic SQL solution is the only possible choice.
Don't let min/max confuse you: There will always be exactly 0 or 1 item per aggregation. The syntax requires an aggregate for theoretical correctness, but if (teacher, student) is unique the aggregate is doing nothing. It does no harm and it does not alter the results.
The approach is right just the way it is. Actually, I am working on the same type of code right now in this minute (which is funny).
You can use row_number
to get the result you want.
SET @dynamic_pivot_query = 'select ' + @teacherList +
'from
(
SELECT [teacher],[student], row_number() over(partition by teacher order by student) as rn
FROM [dbo].[myTable]
) as S
Pivot
(
MIN([student])
FOR teacher IN (' + @teacherList + ')
) as P
'
Update:
To remove the SQL Injection vulnerability you should use quotename
to properly quote your field list.
SELECT @teacherList = Stuff((SELECT DISTINCT',' + quotename(teacher)
FROM myTable
FOR xml path('')), 1, 1, '')
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.