SQL Pivot动态列STUFF函数为空单元格

时间:2013-07-21 03:47:56

标签: sql pivot dynamic-columns

使用STUFF函数执行SQL Pivot动态列,但没有获得我想要的结果

这是SQL Fiddle http://sqlfiddle.com/#!3/241c2/6/0

我可以做些什么来摆脱所有null \ empty单元格?

我希望得到的结果是这样的,其中每列显示每个学生被分配到的课程列表而没有一堆空白单元格

Tom     Harry       Mary        Sue     Paul
Algebra     Algebra     Algebra     Algebra     Geometry
French      French      Spanish     Spanish     Art
Biology     Physics             Physics     Biology

编辑:请求在此处显示代码:

create table clsassin

(

    ClassID int,

    AssignID int,

    ClsNm varchar(10),

    StudntNm varchar(10),

)



insert into clsassin values (1, 1, 'Algebra', 'Tom')

insert into clsassin values (1, 2, 'Algebra', 'Harry')

insert into clsassin values (1, 3, 'Algebra', 'Mary')

insert into clsassin values (1, 4, 'Algebra', 'Sue')

insert into clsassin values (2, 5, 'Geometry', 'Paul')

insert into clsassin values (3, 6, 'French', 'Harry')

insert into clsassin values (3, 7, 'French', 'Tom')

insert into clsassin values (4, 8, 'Spanish', 'Mary')

insert into clsassin values (4, 9, 'Spanish', 'Sue')

insert into clsassin values (5, 10, 'Art', 'Paul')

insert into clsassin values (6, 11, 'Biology', 'Tom')

insert into clsassin values (6, 12, 'Biology', 'Paul')

insert into clsassin values (7, 13, 'Physics', 'Harry')

insert into clsassin values (7, 14, 'Physics', 'Sue')

insert into clsassin values (8, 15, 'History', 'Sue')

DECLARE @cols AS NVARCHAR(MAX),

    @query  AS NVARCHAR(MAX)



select @cols = STUFF((SELECT distinct ',' + QUOTENAME(StudntNm) 
                  FROM clsassin 

FOR XML PATH(''), TYPE

).value('.', 'NVARCHAR(MAX)') 

,1,1,'')



set @query = 'SELECT ' + @cols + ' from 

    (

        select StudntNm, ClsNm
, ClassID                
        from clsassin

    ) x

    pivot 

    (

        min(ClsNm)

        for StudntNm in (' + @cols + ')

    ) p '



execute(@query)

2 个答案:

答案 0 :(得分:4)

原始查询的问题是您在classid PIVOT数据列表中包含select。您有8个不同的classid值,然后在枢轴中应用聚合函数时将对其进行分组。

问题在于,如果您排除classid并应用数据透视表,则每位学生只返回一个值 - 与min(ClsNm)匹配的值

由于您希望显示每个学生的每个班级,因此您应该考虑使用row_number()窗口函数而不是classid。如果您应用row_number()并按studntNm对数据进行分区,那么您将为每个学生分配一个递增的数字,然后在汇总数据时,您将返回每一行。

代码将是:

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

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(StudntNm) 
                  FROM clsassin 
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT ' + @cols + ' 
            from 
            (
                select StudntNm, ClsNm,
                  row_number() over(partition by StudntNm
                                      order by ClsNm) rn
                from clsassin
            ) x
            pivot 
            (
                min(ClsNm)
                for StudntNm in (' + @cols + ')
            ) p '

execute sp_executesql @query;

SQL Fiddle with Demo。这将给你结果:

|   HARRY |    MARY |     PAUL |     SUE |     TOM |
----------------------------------------------------
| Algebra | Algebra |      Art | Algebra | Algebra |
|  French | Spanish |  Biology | History | Biology |
| Physics |  (null) | Geometry | Physics |  French |
|  (null) |  (null) |   (null) | Spanish |  (null) |

答案 1 :(得分:0)

我使用此方法显示来自销售的汇总表,例如:

产品,Jan2013,Feb2013,.....

使用FOR XML PATH('')方法返回所有月份,但不会对它们进行排序。我可以按照正确的顺序对它们进行排序吗?我在下面附上了我的代码:

SET @cols = STUFF((SELECT distinct ',' + '[' + DATENAME(month,DateTime) + DATENAME(year,DateTime) +']' AS MonthYear 
                from DRGCase dc INNER JOIN Company c ON dc.HospitalId=c.CompanyId 
                WHERE dc.DischargeDate > @StartDate AND dc.DischargeDate <= DATEADD(DAY,1,@Enddate)
                FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'');

SELECT @query='SELECT Hospital,' + @cols + 
    'FROM
    (
    SELECT c.CompanyName AS Hospital, DATENAME(month,DateTime) + DATENAME(year,DateTime) AS MonthYear,COUNT(*) AS Cases 

    FROM DRGCase dc INNER JOIN Company c ON dc.HospitalId=c.CompanyId 

    WHERE dc.DischargeDate > ''' + CONVERT(CHAR(10),@StartDate,126) + ''' AND dc.DischargeDate <= DATEADD(DAY,1,''' + CONVERT(CHAR(10),@EndDate,126) + ''')

    GROUP BY c.CompanyName, DATENAME(month,DateTime) + DATENAME(year,DateTime)
    ) ps PIVOT
    (
        sum(Cases)
        FOR MonthYear IN (' + @cols + ')
    )
    as pvt'
exec(@query)