4

我正在尝试将表格数据处理成更具视觉吸引力的输出格式。这可能是问题的一部分,因为我想要的可能是用于单独的报告软件。

我有一张看起来像这样的桌子

teacher    student
----------------------
teacher1   Bob
teacher1   Jim
teacher2   Sam
teacher3   Bill
teacher3   John
teacher3   Eric

我想要一个看起来像这样的表:

teacher1    teacher2    teacher3
---------------------------------
Bob         Sam          Bill
Jim         null         John
null        null         Eric

因此,我尝试将所有教师姓名填充到一个变量中,然后使用 aPivot但由于我必须选择一个聚合,所以我只能像这样得到MaxorMin学生:

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)  

结果是:

teacher1    teacher2    teacher3
---------------------------------
Bob         Sam          Bill

假设如下:

  1. # 教师及其姓名未知(变量)
  2. 每位教师的学生人数是未知的,并且可能因每位教师而异

有没有办法做到这一点?

4

2 回答 2

2

不。

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).

于 2012-04-23T17:54:34.100 回答
1

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, '') 
于 2012-04-23T18:27:56.537 回答