2009-11-05 5 views
7

Disons que j'ai des données, que ce soit dans une table SQL Server 2008 ou une variable -typed [table]:Utilisation de PIVOT dans SQL Server 2008

author_id  review_id  question_id  answer_id 
88540   99001   1    719 
88540   99001   2    720 
88540   99001   3    721 
88540   99001   4    722 
88540   99001   5    723 
36414   24336   1    302 
36414   24336   2    303 
36414   24336   3    304 
36414   24336   4    305 
36414   24336   5    306 

Je veux récupérer les données comme un ensemble de résultats ressemble à ceci:

author_id  review_id  1  2  3  4  5 
88540   99001   719 720 721 722 723 
36414   24336   302 303 304 305 306 

Je soupçonne que l'opérateur PIVOT est ce que je dois (selon this post, de toute façon), mais je ne peux pas comprendre comment démarrer, surtout lorsque le nombre de question_id lignes dans la table peut varier. Dans l'exemple ci-dessus, il s'agit de 5, mais dans une autre requête, la table peut contenir 7 questions distinctes.

Répondre

9

En fait, vous feriez mieux de le faire dans le client. Supposons que vous utilisez Reporting Services, récupérez les données selon votre premier jeu de résultats et affichez-les en utilisant une matrice, avec author_id et review_id dans le groupe de lignes, question_id dans le groupe de colonnes et MAX (answer_id) au milieu.

Une requête est faisable, mais vous auriez besoin de SQL dynamique en ce moment.

... quelque chose comme:

DECLARE @QuestionList nvarchar(max); 
SELECT @QuestionList = STUFF(
(SELECT ', ' + quotename(question_id) 
FROM YourTable 
GROUP BY question_id 
ORDER BY question_id 
FOR XML PATH('')) 
, 1, 2, ''); 

DECLARE @qry nvarchar(max); 
SET @qry = ' 
SELECT author_id, review_id, ' + @QuestionList + 
FROM (SELECT author_id, review_id, question_id, answer_id 
     FROM YourTable 
    ) 
PIVOT 
(MAX(AnswerID) FOR question_id IN (' + @QuestionList + ')) pvt 
ORDER BY author_id, review_id;'; 

exec sp_executesql @qry; 
+0

Cela semble être ce dont j'ai besoin. Je vais essayer et rendre compte - merci! –

+1

Veuillez garder à l'esprit la sous-requête. Si vous utilisez simplement "SELECT * FROM YourTable", toutes les autres colonnes concernées affecteront le regroupement implicite fourni par la fonction PIVOT. Et si vous avez des erreurs, commentez la ligne 'exec', en la remplaçant par' select @ qry' –

+0

Je n'utilise plus jamais [SELECT *] - j'indique toujours explicitement les colonnes auxquelles j'accède - donc ça ne sera pas un problème. Et oui, j'utilisais [select @qry] pendant un moment pour que je puisse voir/déboguer l'instruction SQL avant qu'elle ne s'exécute. Votre code a fonctionné comme promis - merci beaucoup pour votre aide! –

0
select * 
from @t pivot 
(
    max(answer_id) for question_id in ([1],[2],[3],[4],[5]) 
) pivotT 

Le seul moyen pour faire varier la liste ([1], [2], [3], [4], [5]) serait de construire cette requête dans une chaîne (dynamiquement), puis exécuter il.

3

Here vous avez bel exemple et une explication.

Dans votre cas, il serait comme ceci:

SELECT author_id, review_id, [1], [2], [3], [4], [5] 
FROM 
    (
     SELECT author_id, review_id, question_id, answer_id 
     FROM the_table 
    ) up 
PIVOT (MAX(answer_id) FOR question_id IN ([1],[2],[3],[4],[5])) AS pvt 
0

Voir this answer

Fondamentalement, vous pré inspectent les données pour obtenir les colonnes puis générer dynamiquement SQL en utilisant la liste de pivot dynamique. Il n'y a vraiment pas de manière non-dynamique, car la définition des colonnes de l'ensemble que vous voulez retourner n'est pas figée.

2
SELECT author_id, review_id, [1], [2], [3], [4], [5] 
FROM 
    (
     SELECT author_id, review_id, question_id, answer_id 
     FROM the_table 
    ) up 
PIVOT (MAX(answer_id) FOR