2013-06-05 3 views
-1

J'ai une table avec ce schéma:Utilisation de UNPIVOT avec SQL dynamique

tblResults

Question1 | Question2 | Question3 | etc | etc | Question240 | 

Dans ces colonnes Les valeurs peuvent être des éléments suivants:

1, 2, 3, 4, N, M 

J'ai besoin de présenter le des données comme celle-ci:

| QuestionNumber | 1 | 2 | 3 | 4 | N | M | 
------------------------------------------ 
| Question1  | 53| 27| 10| 5 | 2 | 3 | 
| etc   | 20| 40| 32| 8 | 0 | 0 | <-- These values being % (but I can do the calculation later). 
| etc   | 

Je dois pouvoir contrôler le nombre de lignes que le jeu de résultats va produire. Je l'ai fait en procédant comme suit (3 colonnes seulement):

DECLARE @cname VARCHAR(MAX) 
SELECT @cname = STUFF((
    SELECT ', ' + COLUMN_NAME 
    FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE (TABLE_NAME = 'tblResults') AND (ORDINAL_POSITION BETWEEN 8 AND 10) 
    FOR XML PATH(''), TYPE).value('.', 'varchar(max)'), 1,1,'') 

DECLARE @sql NVARCHAR(MAX) 
SET @sql = 'SELECT Answers, CASE WHEN Answer = '''' THEN ''N'' ELSE Answer END AS Answer, COUNT(Answer) AS Total 
      FROM (
       SELECT '[email protected]+' 
       FROM tblResults 
       WHERE (something = ''006'') AND (somethingElse = ''ABC'') 
       ) AS MyTable 
      UNPIVOT (Answer FOR Answers IN ('[email protected]+')) AS MyUnPivot 
      GROUP BY Answers, Answer 
      ORDER BY Answers, Answer' 

exec sp_executesql @sql 

Cela produit l'ensemble de résultat suivant:

| Answers | Answer | Total | 
---------------------------- 
|Question1| 1 | 12474 | 
|Question1| 2 | 188 | 
|Question1| 3 | 200 | 
|Question1| 4 | 5  | 
|Question1| N | 0  | 
|Question1| M | 142 | 
|Question2| 1 | 14521 | 
|etc  |  |  | 
|etc  |  |  | 

D'où mon plan était d'utiliser SQL dynamique que je ne peux pas penser tout autre moyen de le faire. J'ai essayé différentes méthodes UNPIVOT mais je n'arrive pas à progresser. Avant que quelqu'un ne me dise que c'est un mauvais design, je sais que c'est quelque chose dont j'ai hérité et qui ne peut pas être changé sans réécrire une application tierce.

Si quelqu'un peut penser à un meilleur titre s'il vous plaît modifier.

Merci.

+0

Pouvez-vous publier des échantillons de population supplémentaires? Que deviennent les nouveaux en-têtes des colonnes et quelles sont les valeurs sous chaque en-tête? – Taryn

+0

@bluefeet J'ai ajouté ce que j'ai déjà, les 'COUNT' sont corrects mais je dois obtenir les valeurs de' Answer' en colonnes. –

+0

En fonction du jeu de résultats généré par votre requête actuelle, que voulez-vous que le résultat final soit? – Taryn

Répondre

1

D'après les informations que vous avez fournies, vous devez PIVoter les valeurs des réponses dans des colonnes. Puisque vos réponses sont une valeur statique (1, 2, 3, 4, N, M), vous pouvez coder ces valeurs dans votre requête.

Cependant, vous devrez toujours utiliser le SQL dynamique pour déplier les colonnes correctes. Le code sera similaire à ce qui suit:

DECLARE @colsUnpivot AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX) 

select @colsUnpivot = STUFF((SELECT distinct ','+ quotename(c.column_name) 
        from INFORMATION_SCHEMA.COLUMNS as C 
        where (TABLE_NAME = 'tblResults') and 
         (c.ORDINAL_POSITION BETWEEN 3 AND 5) 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query 
    = 'select questionNumber, [1], [2], [3], [4], [N], [M] 
    from 
    (
     select questionNumber, answer 
     from 
     (
      select '[email protected]+' 
      from tblResults 
     ) x 
     unpivot 
     (
      answer 
      for questionNumber in ('+ @colsunpivot +') 
     ) u 
    ) d 
     pivot 
     (
     count(answer) 
     for answer in ([1], [2], [3], [4], [N], [M]) 
    ) piv' 

exec(@query); 

Voir SQL Fiddle with Demo. Ceci donne un résultat:

| QUESTIONNUMBER | 1 | 2 | 3 | 4 | N | M | 
------------------------------------------ 
|  Question3 | 1 | 1 | 1 | 1 | 1 | 1 | 
|  Question4 | 1 | 0 | 1 | 2 | 1 | 1 | 
|  Question5 | 1 | 1 | 1 | 0 | 1 | 2 | 
+0

Merci beaucoup, parfait. Pouvez-vous expliquer PIVOT et UNPIVOT, j'ai utilisé UNPIVOT avant, mais je ne comprends pas comment cela fonctionne dans ce scénario, en utilisant les deux ensemble. –

+0

@JackPettinger L'UNPIVOT normalise vos données de plusieurs colonnes en plusieurs lignes.Une fois que vous obtenez le résultat dans les lignes multiples, vous voulez afficher le nombre total de chaque réponse sous la forme d'une colonne. Le PIVOT utilise une fonction d'agrégat 'count()' et vous fournissez ensuite la liste des valeurs que vous voulez convertir en colonnes, ceci est votre liste de réponses. J'espère que cela aide, laissez-moi savoir si vous avez d'autres questions. – Taryn