Sql server 如何在SQL Server 2008中将行更改为列(多个表、联接等)
我需要帮助为调查应用程序创建报告。 涉及5个主要表格:Sql server 如何在SQL Server 2008中将行更改为列(多个表、联接等),sql-server,pivot,dynamic-sql,dynamic-columns,Sql Server,Pivot,Dynamic Sql,Dynamic Columns,我需要帮助为调查应用程序创建报告。 涉及5个主要表格: 调查(ID、报告列名称) 节(ID、节名称) 调查部分(FK调查、FK调查部分、活动) Section_Surveys_ScoreValue(FK_Surveys,FK_Section,FK_ScoreCategories,Section ScoreValue) ScoreCategories(ID、ScoreStart、ScoreEnd、CategoryName) 每次创建调查时,都会生成一个新的ReportColumnName,该列
- 调查(ID、报告列名称)
- 节(ID、节名称)
- 调查部分(FK调查、FK调查部分、活动)
- Section_Surveys_ScoreValue(FK_Surveys,FK_Section,FK_ScoreCategories,Section ScoreValue)
- ScoreCategories(ID、ScoreStart、ScoreEnd、CategoryName)
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
这些调查列是在创建新列时动态添加的,因此它们永远不是常量
每个表都有一个CreateDate
列,默认值为GetDATE()
。我得到的错误是:
为“pvt”多次指定了列“CreateDate”。无法绑定多部分标识符“Sv.ReportColumnName”。
列前缀“SSSV”与查询中使用的表名或别名不匹配 请帮助正确显示我的数据。它应该显示如下内容:
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中的值(根据数字所在的时间间隔,如“良好”、“优秀”等)
多谢各位
编辑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:多亏了乔治,我终于找到了解决方案!下面是最后的代码,它显示了我需要的列:
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)
感谢所有的帮助,感谢“投票否决”(如果我能自己得出结果,我就不会在这里发布了)。使用数据透视拨号时始终使用表格表达式。大概是这样的:
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'
你也可以看看我对类似问题的回答:
我建议先用硬编码的列来写,以确保逻辑正确,然后再转换。另外,如果您发布每个表的示例数据以及表结构,则更容易找出问题所在。您还可以
print@sql
查看查询语法是什么,然后从那里进行调试。能否发布生成此错误的sql变量的示例值?感谢您的回复。我用Print@SQL的值编辑了OP;PIVOT中似乎存在一个问题,即那些动态列名,但我不知道如何修复它们(因为它们的数量会一直变化)。类似的情况似乎在我尝试调整代码的地方起作用。@XYZ只是猜测,但您是否尝试将select'、'+quotename(dt)
更改为select distinct'、'+quotename(dt)
?错误:如果指定了select distinct,则按项目排序必须出现在选择列表中。当我尝试将其添加到ORDERBY子句时,它不起作用(可能是因为其中有一个FORXML路径)!经过几次修改后,我让它工作了(并更新了OP)。