2015-10-20 73 views
1

編輯:我使用Microsoft SQL Server Management Studio來運行我的查詢。 我猜是Microsoft SQL Server標準版(64位)。SQL查詢行到列

我有一個複雜的查詢運行。我不知道該怎麼做,所以我去寫了一個大約500行和許多連接的查詢。不是應該怎麼做圓頂。

我的數據結構爲:

id  user_id  question_id  answer1  
1   1    1    a   
2   1    2    c   
3   1    3    a   
4   2    1    c   
5   2    2    a   
...  ...   ...    ...   

有超過700個用戶。每個用戶已經回答了大約60個問題(次數2,每個問題有2個答案,但是如果我能夠對第一個答案進行很好的查詢,這是無關緊要的)。有一些問題我不感興趣(實際上應該跳過)。

我現在的結果如下(好成績,但查詢是太搖頭):

user_id q1 q2 q3 q4 q8 q9 ... q60 
1   a  b  c  d  b  a  ... a 
2   b  a  c  a  c  b  ... w 
3   y  a  w  ... ... 

所以,基本上我想創建一個數組,說[1,2,3,4,8,9],說我很感興趣那些問題ID和查詢,所以我得到這些列作爲上面的例子。我不知道如何做到這一點。

我現在查詢是這樣的人:

SELECT C.user_id, Q1, Q2, Q3, Q4, Q8, ... 
FROM (
    SELECT A.user_id, Q1, // and here tons of unions 
+0

在這種情況下,您必須編寫Dynamic Sql,即使用數組列表生成查詢,然後執行它。在sql server中你可以通過EXEC運行動態查詢(「Select ...」) – SeeTheC

+0

你的示例數據和輸出不匹配,這是故意的嗎? 此外,標記您的DBMS請求。 – DarkKnight

+1

您正在使用哪些DBMS? Postgres的?甲骨文? –

回答

1

編輯:簡化僅使用ANSWER1:

DECLARE @tbl TABLE(id INT,user_id INT,question_id INT,answer1 VARCHAR(1),answer2 VARCHAR(1)); 
INSERT INTO @tbl VALUES  
(1,1,1,'a','x')   
,(2,1,2,'c','y')   
,(3,1,3,'a','y')   
,(4,2,1,'c','y')   
,(5,2,2,'a','x'); 

WITH AllAnswers AS 
(
    SELECT p.* 
    FROM 
    (
     SELECT tbl.user_id 
       ,'q' + CAST(tbl.question_id AS VARCHAR(10)) AS columnName 
       ,answer1 
     FROM @tbl AS tbl 
    ) AS x 
    PIVOT 
    (
     MIN(answer1) FOR columnName IN(q1,q2,q3 /*Add your question numbers here*/) 
    ) AS p 
) 
SELECT aa.user_id 
     ,aa.q1 
     ,aa.q2 
     ,aa.q3 
     /*Get only the questions you want*/ 
FROM AllAnswers AS aa 

/* Result 

user_id q1 q2 q3 
1  a c a 
2  c a NULL 

*/ 

難道這是你的解決方案:

只是一個簡短的說明:當你爲每個問題寫兩個答案時,我把第二個答案放到測試集中。爲了讓一個PIVOT具有多個列,我使用這個技巧將兩個答案連接爲一個僞XML。這是通過其內部索引再次旋轉和拆分的。

結果是所有用戶的列表,其中包含所有問題的答案。使用最後一個SELECT,您可以選擇要提取的問題/答案。

DECLARE @tbl TABLE(id INT,user_id INT,question_id INT,answer1 VARCHAR(1),answer2 VARCHAR(1)); 
INSERT INTO @tbl VALUES  
(1,1,1,'a','x')   
,(2,1,2,'c','y')   
,(3,1,3,'a','y')   
,(4,2,1,'c','y')   
,(5,2,2,'a','x'); 

WITH AllAnswers AS 
(
    SELECT p.user_id 
      ,CAST(p.q1 AS XML).value('x[1]','varchar(1)') AS q1_1 
      ,CAST(p.q1 AS XML).value('x[2]','varchar(1)') AS q1_2 
      ,CAST(p.q2 AS XML).value('x[1]','varchar(1)') AS q2_1 
      ,CAST(p.q2 AS XML).value('x[2]','varchar(1)') AS q2_2 
      ,CAST(p.q3 AS XML).value('x[1]','varchar(1)') AS q3_1 
      ,CAST(p.q3 AS XML).value('x[2]','varchar(1)') AS q3_2 
      /*Add all your question numbers here*/ 
    FROM 
    (
     SELECT tbl.user_id 
       ,'q' + CAST(tbl.question_id AS VARCHAR(10)) AS columnName 
       ,'<x>' + ISNULL(answer1,'') + '</x><x>' + ISNULL(answer2,'') + '</x>' AS BothAnswers 
     FROM @tbl AS tbl 
    ) AS x 
    PIVOT 
    (
     MIN(BothAnswers) FOR columnName IN(q1,q2,q3 /*Add your question numbers here*/) 
    ) AS p 
) 
SELECT aa.user_id 
     ,aa.q1_1 
     ,aa.q1_2 
     ,aa.q2_1 
     ,aa.q2_2 
     ,aa.q3_1 
     ,aa.q3_2 
     /*Get only the questions you want*/ 
FROM AllAnswers AS aa 
+0

我會開始工作,感謝精心設計的例子!有了「兩個答案」,我的意思是表格有兩個答案欄(請參閱'答案1',還有'答案2')。我不需要看第二個答案:我需要兩個結果表,一個用於答案1,另一個用於答案2。因此,我可以使用查詢並將其設置爲從answer1列中獲取答案,然後從anwer2列中查詢相同的查詢。 – Tjab

+0

@Tjab,我將我的示例簡化爲僅使用answer1。我不認爲,這可以做得更容易...在最終的SELECT中,您可以自由選擇只選擇您想要的列 – Shnugo

0
SELECT * 
FROM 
(
    SELECT [user_id], 
     [answer1], 
     row_number() OVER(PARTITION BY [user_id] ORDER BY [question_id]) rn 
    FROM [table] 
) d 
PIVOT 
(
    MAX([answer1]) 
    FOR rn in ([1], [2], [3], [4], [5], [6]) 
) piv 

工作得非常好,對於一個錯誤。 user_id = 1question_id = 3沒有答案,但是對於question_id = 4。我的結果放在4答案中3

user_id 1 2 3 4 5 6 
1   a b c   NULL NULL 
2   a b c d NULL NULL 

有了這些數據:

user_id question_id answer1 
1   1    a 
1   2    b 
1   4    c 
1   5          (anwer1 = empty string) 
1   6    NULL 
2   1    a 
2   2    b 
2   4    c 
2   5    d 
2   6    NULL 

應該給:

user_id 1 2 3 4 5 6 
1   a b NULL c   NULL 
2   a b NULL c d NULL 

所以錯誤:如果沒有找到記錄,使用「下一個問題」的答案。

+0

ROW_NUMBER將返回一個運行數字。如果表中沒有答案,你的「rn」將跳過一個值。你可以嘗試使用Tally-Table,但我的答案肯定更可靠......它有什麼問題? – Shnugo

+0

嗨,你能解決你的問題嗎?我的(已編輯)答案是否對你有幫助?如果是的話,它會非常友好的投票它 - 如果它解決了你的問題 - 標記爲接受,thx! – Shnugo

+0

是的,謝謝!對不起,我很晚很晚纔回來。標記爲已接受,再次感謝! – Tjab