如何在 SQL Server 2008 中将行更改为列(多个表、联接等)

How to change rows into columns in SQL Server 2008 (multiple tables, joins etc)

我需要帮助创建调查应用程序的报告。 主要涉及5张表:

每次创建调查时,都会生成一个新的 ReportColumnName,它需要成为报告中的一个列。对于这些列中的每一列,以及每个部分(在调查中处于活动状态),都会有一个 SectionScoreValue。这进一步链接并检查它是否在 ScoreCategories 的间隔内,并为每个调查和部分显示结果类别 (CategoryName)。

几天来我一直在寻找如何正确旋转这些列并正确显示所需值的方法。通过对从网站上获得的一些代码进行改编,我认为这会起作用:

declare @SQL nvarchar(max), @Cols nvarchar(max)
select @Cols = 
stuff(
(
  select ', ' + quotename(dt)
  from 
  (
    select TOP 100 PERCENT Sv.ID, Sv.ReportColumnName as dt 
    from Surveys AS Sv
    ORDER BY Sv.ID
  ) X
  ORDER BY X.ID FOR XML PATH('')
),1,1,''
)

SELECT @Cols

set @SQL = 
'SELECT Sv.ReportColumnName, SSSV.* 
FROM Surveys AS Sv 
INNER JOIN Sections_Surveys__ScoreValues AS SSSV
   ON SSSV.FK_Surveys_ID = Sv.ID
INNER JOIN Sections AS Sc
   ON Sc.ID = SSSV.FK_Sections_ID
INNER JOIN Sections_Surveys AS SS 
   ON SS.FK_Surveys_ID = Sv.ID
   AND SS.FK_Sections_ID = Sc.ID
INNER JOIN ScoreCategories AS ScoreC 
   ON ScoreC.ID = SSSV.FK_ScoreCategories_ID

PIVOT (max(SSSV.SectionScoreValue) FOR Sv.ReportColumnName IN (' + @Cols
+')) pvt'

execute (@sql)

@Cols 变量包含我需要的列(即调查的名称)并正确显示它们(并以逗号分隔)。所以这部分工作正常。

我的问题是下一部分应该(最初)为每个 SectionName(在第一列)和每个调查(每个单独的调查)放置 SectionScoreValue列)。

这些调查列是在创建新列时动态添加的,因此它们从来都不是一个常数。

这些表中的每一个都有一个默认为 GetDATE()CreateDate 列。我得到的错误是:

The column 'CreateDate' was specified multiple times for 'pvt'.
The multi-part identifier "Sv.ReportColumnName" could not be bound.
The column prefix 'SSSV' does not match with a table name or alias name used in the query.

请帮助正确显示我的数据。它应该显示如下内容:

Section Survey1 Survey2 Survey3 ......
s1        1.33    1.66    2.5
s2        0.00    3.33    4
s3        2.33    2       1.66
s4        0.66    2.5     3

数字也可以替换为 ScoreCategoryName 中的值(如 'Good'、'Excellent' 等,根据数字所在的区间)。

谢谢

编辑 1:这就是 PRINT @SQL 的结果:

SELECT Sv.ReportColumnName, SSSV.* 
FROM Surveys AS Sv 
INNER JOIN Sections_Surveys__ScoreValues AS SSSV
    ON SSSV.FK_Surveys_ID = Sv.ID
INNER JOIN Sections AS Sc
    ON Sc.ID = SSSV.FK_Sections_ID
INNER JOIN Sections_Surveys AS SS 
    ON SS.FK_Surveys_ID = Sv.ID
    AND SS.FK_Sections_ID = Sc.ID
INNER JOIN ScoreCategories AS ScoreC 
    ON ScoreC.ID = SSSV.FK_ScoreCategories_ID

PIVOT (max(SSSV.SectionScoreValue) FOR Sv.ReportColumnName 
IN ( [S1-1-2 -3], [S217], [al 3], [S37], [R4], [ult_nume_col])) pvt

编辑 2: 感谢 Giorgi,我设法找到了解决方案!这是最终代码,它显示了我所需要的列:

declare @SQL nvarchar(max), @Cols nvarchar(max)
select @Cols = 
stuff(
(
    select ', ' + quotename(dt)
    from 
    (
        select TOP 100 PERCENT Sv.ID, Sv.ReportColumnName as dt 
        from Surveys AS Sv
        ORDER BY Sv.ID
    ) X
    ORDER BY X.ID FOR XML PATH('')



),1,1,''
)

SELECT @Cols

SET @SQL = ';
WITH    cte
          AS ( SELECT Sv.CreateDate, Sv.ReportColumnName, Sc.SectionName, SSSV.SectionScoreValue 
                FROM Surveys AS Sv 
                INNER JOIN Sections_Surveys__ScoreValues AS SSSV
                    ON SSSV.FK_Surveys_ID = Sv.ID
                INNER JOIN Sections AS Sc
                    ON Sc.ID = SSSV.FK_Sections_ID
                INNER JOIN Sections_Surveys AS SS 
                    ON SS.FK_Surveys_ID = Sv.ID
                    AND SS.FK_Sections_ID = Sc.ID
                INNER JOIN ScoreCategories AS ScoreC 
                    ON ScoreC.ID = SSSV.FK_ScoreCategories_ID
             )
    SELECT  SectionName , ' + @Cols + '
    FROM    cte PIVOT ( MAX(cte.SectionScoreValue) FOR cte.ReportColumnName IN (' + @Cols + ') ) pvt'

print @sql

execute (@sql)

感谢大家的帮助,感谢 "vote down"(如果我能自己得到结果,我就不会在这里发布)。

旋转拨号时始终使用 table 表达式。像这样:

SET @SQL = ';
WITH    cte
          AS ( SELECT   SSSV.SectionScoreValue ,
                        Sv.ReportColumnName ,
                        Section
               FROM     Surveys AS Sv
                        INNER JOIN Sections_Surveys__ScoreValues AS SSSV ON SSSV.FK_Surveys_ID = Sv.ID
                        INNER JOIN Sections AS Sc ON Sc.ID = SSSV.FK_Sections_ID
                        INNER JOIN Sections_Surveys AS SS ON SS.FK_Surveys_ID = Sv.ID AND SS.FK_Sections_ID = Sc.ID
                        INNER JOIN ScoreCategories AS ScoreC ON ScoreC.ID = SSSV.FK_ScoreCategories_ID
             )
    SELECT  Section , ' + @Cols + '
    FROM    cte PIVOT ( MAX(SSSV.SectionScoreValue) FOR Sv.ReportColumnName IN (' + @Cols + ') ) pvt'

也可以看看我对类似问题的回答: