【问题标题】:SQL Pivot Dynamic Columns STUFF function empty cellsSQL Pivot Dynamic Columns STUFF 函数空单元格
【发布时间】:2013-07-21 03:47:55
【问题描述】:

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

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

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

我希望结果显示是这样的,每列显示每个学生分配到的班级列表,而不是一堆空白单元格

汤姆哈里玛丽苏保罗 代数 代数 代数 代数 几何 法国 法国 西班牙 西班牙 艺术 生物学 物理学 物理学 生物学

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

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)

【问题讨论】:

  • 请将您的代码添加到问题正文中,不鼓励严重依赖第三方链接。链接可能会失效,让您的问题无法回答

标签: sql pivot dynamic-columns


【解决方案1】:

原始查询的问题是您将 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) |

【讨论】:

  • 非常感谢您的帮助 bluefeet。看起来很棒!
【解决方案2】:

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

产品,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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-20
    • 2014-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-10
    • 1970-01-01
    • 2021-05-22
    相关资源
    最近更新 更多