【问题标题】:SQL Server - Dynamic Pivot using existing tableSQL Server - 使用现有表的动态数据透视
【发布时间】:2016-07-21 21:07:21
【问题描述】:

我有以下问题

SELECT CONCAT(RIGHT('00' + CONVERT(VARCHAR(2),Procedures.SeriesNum),2),'-',RIGHT('0000' + CONVERT(VARCHAR(4),Procedures.ProcNum),4)) AS 'Procedure',
Procedures.Description,
Procedures.CurrentRev,
Procedures.DayToDayLevel,
Procedures.MaxLevel,
Users.Username,
UsersProcedures.RevTrained,
UsersProcedures.LevelTrained
FROM Procedures
CROSS JOIN Users
LEFT JOIN UsersProcedures ON UsersProcedures.Username = Users.Username AND Procedures.SeriesNum = UsersProcedures.SeriesNum AND Procedures.ProcNum = UsersProcedures.ProcNum

返回以下结果: 但是我想使用 Pivot 以便每个用户的信息(特别是他们接受培训的级别显示为列中的值(列标题是用户名的标题)。

我想忽略 CurrentRev,而是为每个程序的每个修订版设置 1 行(如果没有用户接受过当前修订版的培训 - 无论用户是否接受过该程序的任何先前修订版的培训,那应该在那里作为一个空行),如下所示:

我认为我需要使用透视,虽然我以前从未尝试过,而且我在网上看到的示例似乎对透视列使用静态列表,而我想使用所有记录用户表。

我应该指出,在数据网格中显示结果时,为了清晰起见,它会被着色。

我将如何尝试这个?

更新:我已经了解了这个查询

SELECT *
FROM (SELECT CONCAT(RIGHT('00' + CONVERT(VARCHAR(2),Procedures.SeriesNum),2),'-',RIGHT('0000' + CONVERT(VARCHAR(4),Procedures.ProcNum),4)) AS 'Procedure',
Procedures.Description,
Procedures.CurrentRev,
UsersProcedures.RevTrained,
Users.Username,
UsersProcedures.LevelTrained FROM Procedures CROSS JOIN Users LEFT JOIN UsersProcedures ON UsersProcedures.Username = Users.Username AND Procedures.SeriesNum = UsersProcedures.SeriesNum AND Procedures.ProcNum = UsersProcedures.ProcNum) AS Procs
  PIVOT
  (
    MAX(LevelTrained)
    FOR Procs.Username
    IN(User1,User2,User3)
  ) AS PivotTable

这给了我这个:

但是,我仍然希望将结果进一步分组,类似于我的第二个屏幕截图。即,如果至少有 1 个用户已经接受过特定修订的培训,那么也不要为该修订显示另一个空行。

如果 RevTrained 为 NULL,则在其位置显示 CurrentRev。

【问题讨论】:

  • 是的,您需要动态轴。这需要一些工作。请参阅this question 以获得一些见解。稍后我会尽量多找些时间来帮助你。
  • 我应该补充一点,我能找到的所有示例都涉及聚合 Pivot 数据,但我实际上并不想这样做。这是我想为每个用户显示的单个值(该程序的培训级别及其修订版)。

标签: sql-server pivot


【解决方案1】:

好的,下面是完成的解决方案,使用动态查询获取所有用户,并使用 IF 语句解决上述问题:

如果至少有 1 位用户已经接受过特定修订版的培训,那么也不要为该修订版显示另一个空行。 此外,如果 RevTrained 为 NULL,则在其位置显示 CurrentRev。

DECLARE @users AS VARCHAR(MAX),@query AS VARCHAR(MAX)
SELECT @users  = STUFF((SELECT ',' + CONCAT('[',Username,']') FROM Users FOR XML PATH(''),TYPE).value('.', 'VARCHAR(MAX)'),1,1,'')
SET @query = 'SELECT *
FROM (SELECT CONCAT(RIGHT(''00'' + CONVERT(VARCHAR(2),Procedures.SeriesNum),2),''-'',RIGHT(''0000'' + CONVERT(VARCHAR(4),Procedures.ProcNum),4)) AS ''Procedure Number'',
CASE WHEN UsersProcedures.RevTrained IS NULL THEN Procedures.CurrentRev ELSE UsersProcedures.RevTrained END AS ''Revision'',
Procedures.Description,
Procedures.DayToDayLevel AS ''Maxmimum Training Level'',
Procedures.DayToDayLevel AS ''Training level for Day to Day Usage'', 
Users.Username,
UsersProcedures.LevelTrained FROM Procedures CROSS JOIN Users LEFT JOIN UsersProcedures ON UsersProcedures.Username = Users.Username AND Procedures.SeriesNum = UsersProcedures.SeriesNum AND Procedures.ProcNum = UsersProcedures.ProcNum) AS Procs
PIVOT(
MAX(LevelTrained)
FOR Procs.Username
IN('+@users+')) AS PivotTable'
execute(@query);

【讨论】:

    猜你喜欢
    • 2013-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-16
    • 2014-07-26
    • 1970-01-01
    • 2010-11-29
    • 2011-12-10
    相关资源
    最近更新 更多