旋转未定义的文本列
Pivoting Undefined Text Columns
我有 2 table 的数据需要在 SQL 服务器查询中结合在一起 - 一个包含交易信息,另一个包含已针对交易回答的营销问题。
这是一个精简的例子:
-------------------------------------------
| Transaction Info |
|-------------------------------------------|
|Transaction_ID |Date |Customer_ID|
|1 |2016-01-01 |2614 |
|2 |2016-04-16 |3981 |
|3 |2016-06-25 |2113 |
-------------------------------------------
------------------------------------------------------------------
| Marketing Questions |
|------------------------------------------------------------------|
|Transaction_ID |Question |Answer |
|1 |How would you rate our service? |Excellent |
|2 |Would you recommend us? |Yes |
|2 |Where did you hear about us? |Friend |
|1 |Any other comments? |None |
|3 |How would you rate our service? |Average |
|2 |Any other comments? |None |
------------------------------------------------------------------
这是我卡住的地方:我需要将营销 table 中的问题转变成最终连接 table 中的列名称,其中单元格值是答案。
问题是这些问题是从一个非常大的集合中随机抽取的,所以我无法在查询中定义它们。它需要动态捕获 table 中返回的所有问题,将它们生成为列,并在单元格中填充答案。
营销 table 本身是日期范围内查询的结果,因此包含的问题并不总是相同的。这就是为什么我不能提前在 PIVOT 中定义它们。
我真的不知道从哪里开始,所以非常感谢您的帮助!
再次强调,PIVOT 很棒,但我使用动态数据透视的存储过程
不确定您想要的输出,但您可以使用 parameters/group by's
Select A.*
,B.Question
,B.Answer
Into #Temp
From Transction A
Join Marteting B
on (A.Transaction_ID=B.Transaction_ID)
Exec [prc-Pivot] '#Temp','Question','max(Answer)[]','Customer_ID,Transaction_ID,Date','count(*)[Records]'
Returns
存储过程
CREATE PROCEDURE [dbo].[prc-Pivot] (
@Source varchar(1000), -- Any Table or Select Statement
@PvotCol varchar(250), -- Field name or expression ie. Month(Date)
@Summaries varchar(250), -- aggfunction(aggValue)[optionalTitle]
@GroupBy varchar(250), -- Optional additional Group By
@OtherCols varchar(500) ) -- Optional Group By or aggregates
AS
--Exec [prc-Pivot] 'Select Year=Year(TR_Date),* From [Chinrus-Series].[dbo].[DS_Treasury_Rates]','''Q''+DateName(QQ,TR_Date)','avg(TR_Y10)[-Avg]','Year','count(*)[Records],min(TR_Y10)[Min],max(TR_Y10)[Max],Avg(TR_Y10)[Avg]'
--Exec [prc-Pivot] '#Temp','Attribute','max(Description)[]','ID','count(*)[Records]'
Set NoCount On
Set Ansi_Warnings Off
Declare @Vals varchar(max),@SQL varchar(max);
Set @Vals = ''
Set @OtherCols= IsNull(', ' + @OtherCols,'')
Set @Source = case when @Source Like 'Select%' then @Source else 'Select * From '+@Source end
Create Table #TempPvot (Pvot varchar(100))
Insert Into #TempPvot
Exec ('Select Distinct Convert(varchar(100),' + @PvotCol + ') as Pvot FROM (' + @Source + ') A')
Select @Vals = @Vals + ', isnull(' + Replace(Replace(@Summaries,'(','(CASE WHEN ' + @PvotCol + '=''' + Pvot + ''' THEN '),')[', ' END),0) As [' + Pvot ) From #TempPvot Order by Pvot
Drop Table #TempPvot
Set @SQL = Replace('Select ' + Isnull(@GroupBy,'') + @OtherCols + @Vals + ' From (' + @Source + ') PvtFinal ' + case when Isnull(@GroupBy,'')<>'' then 'Group By ' + @GroupBy + ' Order by ' + @GroupBy else '' end,'Select , ','Select ')
--Print @SQL
Exec (@SQL)
Set NoCount Off
Set Ansi_Warnings on
您可以使用动态 SQL 轻松实现此目的。例如:
DECLARE @dynPiv varchar(max)
DECLARE @PivotQuery
SET @dynPiv = STUFF((SELECT ',' + QUOTENAME(Question)
FROM MarketingQuestions
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET @PivotQuery = '[YOUR QUERY HERE]
PIVOT ( [YOUR PIVOT GOES HERE] FOR Question IN ' + @dynPiv + ')'
没有输入完整的代码,但这应该传达了这个想法。 @dynPiv 将采用问题的所有不同值的值。打印@dynPiv 以获得更好的可视化效果
我有 2 table 的数据需要在 SQL 服务器查询中结合在一起 - 一个包含交易信息,另一个包含已针对交易回答的营销问题。
这是一个精简的例子:
-------------------------------------------
| Transaction Info |
|-------------------------------------------|
|Transaction_ID |Date |Customer_ID|
|1 |2016-01-01 |2614 |
|2 |2016-04-16 |3981 |
|3 |2016-06-25 |2113 |
-------------------------------------------
------------------------------------------------------------------
| Marketing Questions |
|------------------------------------------------------------------|
|Transaction_ID |Question |Answer |
|1 |How would you rate our service? |Excellent |
|2 |Would you recommend us? |Yes |
|2 |Where did you hear about us? |Friend |
|1 |Any other comments? |None |
|3 |How would you rate our service? |Average |
|2 |Any other comments? |None |
------------------------------------------------------------------
这是我卡住的地方:我需要将营销 table 中的问题转变成最终连接 table 中的列名称,其中单元格值是答案。
问题是这些问题是从一个非常大的集合中随机抽取的,所以我无法在查询中定义它们。它需要动态捕获 table 中返回的所有问题,将它们生成为列,并在单元格中填充答案。
营销 table 本身是日期范围内查询的结果,因此包含的问题并不总是相同的。这就是为什么我不能提前在 PIVOT 中定义它们。
我真的不知道从哪里开始,所以非常感谢您的帮助!
再次强调,PIVOT 很棒,但我使用动态数据透视的存储过程
不确定您想要的输出,但您可以使用 parameters/group by's
Select A.*
,B.Question
,B.Answer
Into #Temp
From Transction A
Join Marteting B
on (A.Transaction_ID=B.Transaction_ID)
Exec [prc-Pivot] '#Temp','Question','max(Answer)[]','Customer_ID,Transaction_ID,Date','count(*)[Records]'
Returns
存储过程
CREATE PROCEDURE [dbo].[prc-Pivot] (
@Source varchar(1000), -- Any Table or Select Statement
@PvotCol varchar(250), -- Field name or expression ie. Month(Date)
@Summaries varchar(250), -- aggfunction(aggValue)[optionalTitle]
@GroupBy varchar(250), -- Optional additional Group By
@OtherCols varchar(500) ) -- Optional Group By or aggregates
AS
--Exec [prc-Pivot] 'Select Year=Year(TR_Date),* From [Chinrus-Series].[dbo].[DS_Treasury_Rates]','''Q''+DateName(QQ,TR_Date)','avg(TR_Y10)[-Avg]','Year','count(*)[Records],min(TR_Y10)[Min],max(TR_Y10)[Max],Avg(TR_Y10)[Avg]'
--Exec [prc-Pivot] '#Temp','Attribute','max(Description)[]','ID','count(*)[Records]'
Set NoCount On
Set Ansi_Warnings Off
Declare @Vals varchar(max),@SQL varchar(max);
Set @Vals = ''
Set @OtherCols= IsNull(', ' + @OtherCols,'')
Set @Source = case when @Source Like 'Select%' then @Source else 'Select * From '+@Source end
Create Table #TempPvot (Pvot varchar(100))
Insert Into #TempPvot
Exec ('Select Distinct Convert(varchar(100),' + @PvotCol + ') as Pvot FROM (' + @Source + ') A')
Select @Vals = @Vals + ', isnull(' + Replace(Replace(@Summaries,'(','(CASE WHEN ' + @PvotCol + '=''' + Pvot + ''' THEN '),')[', ' END),0) As [' + Pvot ) From #TempPvot Order by Pvot
Drop Table #TempPvot
Set @SQL = Replace('Select ' + Isnull(@GroupBy,'') + @OtherCols + @Vals + ' From (' + @Source + ') PvtFinal ' + case when Isnull(@GroupBy,'')<>'' then 'Group By ' + @GroupBy + ' Order by ' + @GroupBy else '' end,'Select , ','Select ')
--Print @SQL
Exec (@SQL)
Set NoCount Off
Set Ansi_Warnings on
您可以使用动态 SQL 轻松实现此目的。例如:
DECLARE @dynPiv varchar(max)
DECLARE @PivotQuery
SET @dynPiv = STUFF((SELECT ',' + QUOTENAME(Question)
FROM MarketingQuestions
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET @PivotQuery = '[YOUR QUERY HERE]
PIVOT ( [YOUR PIVOT GOES HERE] FOR Question IN ' + @dynPiv + ')'
没有输入完整的代码,但这应该传达了这个想法。 @dynPiv 将采用问题的所有不同值的值。打印@dynPiv 以获得更好的可视化效果