旋转未定义的文本列

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 以获得更好的可视化效果