2016-08-16 25 views
1

我有兩個數據表,我需要在一個SQL Server查詢中連接在一起 - 一個包含事務信息,另一個包含已針對事務回答的市場營銷問題。旋轉未定義的文本列

這裏是一個精簡的例子:

------------------------------------------- 
|    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  | 
------------------------------------------------------------------ 

這裏就是我堅持:我需要轉動的營銷表中的問題,成爲列名在最後的連接表,在單元格的值是答案。

問題是,問題是從一個非常大的集合隨機化的,所以我無法在查詢中定義它們。它需要動態捕獲表中返回的所有問題,將它們生成爲列,然後在單元格中填充答案。

營銷表本身就是日期範圍查詢的結果,因此包含的問題並不總是相同的。這就是爲什麼我不能提前將它們定義在PIVOT中的原因。

我真的不知道從哪裏開始,所以任何幫助都非常感謝!

+3

哎喲...它看起來像您的MarketingQuestions嚴重需要正常化。一遍又一遍地重複提問並不是最好的設計。話雖如此,你試圖完成的事情聽起來像是一個動態的關鍵。這裏已經有數百次和數百次的問答。 –

+0

我最近使用遞歸類做了一些事情。我需要在計算機上寫下代碼和測試,但是請稍等片刻 – Merenix

+0

如果應用程序最終是10%DBMS代碼和90%支持代碼,旨在解決DBMS功能中的缺陷,然後(a)選擇不同的DBMS或(b)首先不使用DBMS。 DBMS旨在使任務更簡單,而不是更復雜。如果不是,那麼顯然不合適,並且不適合當前的任務。 –

回答

0

您可以使用動態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 + ')' 

Didnt鍵入了整個代碼,但應該共享這個想法。 @dynPiv將採用Question的所有不同值的值。打印@dynPiv以獲得更好的可視化效果

0

再次,PIVOT是偉大的,但我使用存儲過程的動態支點

不知道您想要的輸出,但是你可以用參數播放/組通過的

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]' 

返回

enter image description here

存儲過程

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 '[email protected] 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 
+0

我發誓我只是在另一篇文章上讀到同樣的東西大聲笑 – Merenix

+0

@Merenix將它保留在我的剪貼板 –

+0

肯定。它是一個interstimg解決方案。儘管我有一個很快的問題,但假設我在一個只允許數據讀取器訪問的組織中工作。你推薦什麼。到目前爲止,我已經完成了ctes並且迴轉,但是通常我只是在辦公桌前哭泣,希望問題消失 – Merenix