Lignes de requête SQL vers les colonnes

Edit: j'utilise Microsoft SQL Server Management Studio pour exécuter mes requêtes. Microsoft SQL Server Standard Edition (64 bits) Je suppose.

J'ai une requête complexe à exécuter. Je n'avais aucune idée de comment le faire, alors je suis allé écrire une requête qui est d'environ 500 lignes et de nombreuses jointures. Pas comment les choses devraient être coupées.

Ma structure de données est:

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

Il y a plus de 700 users. Chaque user a répondu à environ 60 questions (2 fois, il y a 2 réponses à chaque question, mais ce n'est pas pertinent si je peux get une bonne requête pour la première réponse). Il y a des questions qui ne m'intéressent pas (et qui devraient sauter).

Mon résultat actuel est le suivant (bon résultat, mais la requête est trop forte):

 user_id q1 q2 q3 q4 q8 q9 ... q60 1 abcdba ... a 2 bacacb ... w 3 yaw ... ... 

Donc, fondamentalement, je voudrais créer un tableau, disons [1,2,3,4,8,9] , en disant que je suis intéressé par ces identifiants de question, et requête afin que j'obtienne ces colonnes comme l'exemple ci-dessus. Je n'ai aucune idée comment faire ça.

Ma requête actuelle est dans les goûts de:

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

EDIT: simplifié en utilisant seulement 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 aca 2 ca NULL */ 

Cela pourrait-il être une solution pour vous?

Juste une courte explication: Comme vous écrivez à propos de deux réponses pour chaque question, j'ai mis cette deuxième réponse dans l'set de test. Pour autoriser un PIVOT avec plus d'une colonne, j'utilise l'astuce pour concaténer les deux réponses sous la forme d'un pseudo-XML. Ceci est pivoté et démonté par son index interne à nouveau.

Le résultat est une list de tous les users avec toutes les réponses à toutes les questions. Avec le dernier SELECT, vous pouvez choisir les questions / réponses que vous voulez récupérer.

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

Fonctionne très bien, pour un bug. user_id = 1 n'a pas de réponses pour question_id = 3 , mais il a pour question_id = 4 . Mon résultat place la réponse sur 4 à 3 :

 user_id 1 2 3 4 5 6 1 abc NULL NULL 2 abcd NULL NULL 

Avec ces données:

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

Aurait dû donner:

 user_id 1 2 3 4 5 6 1 ab NULL c NULL 2 ab NULL cd NULL 

Donc le bug: si aucun logging n'est trouvé, la réponse à la 'question suivante' est utilisée.