2008-10-17 7 views
16

Je travaille avec un ensemble de données qui ressemble à quelque chose comme ceci.Pivot SQL Server 2005 sur un nombre inconnu de colonnes

StudentName | AssignmentName | Grade 
--------------------------------------- 
StudentA  | Assignment 1 | 100 
StudentA  | Assignment 2 | 80 
StudentA  | Total   | 180 
StudentB  | Assignment 1 | 100 
StudentB  | Assignment 2 | 80 
StudentB  | Assignment 3 | 100 
StudentB  | Total   | 280 

Le nom et le nombre de missions sont dynamiques, je dois obtenir des résultats simlilar à ce qui suit.

Student  | Assignment 1 | Assignment 2 | Assignment 3 | Total 
-------------------------------------------------------------------- 
Student A | 100   | 80   | null   | 180 
Student B | 100   | 80   | 100   | 280 

Maintenant, idéalement, je voudrais trier la colonne basée sur une « date d'échéance » qui pourraient être inclus/associés à chaque mission. Le total devrait être à la fin si possible (Il peut être calculé et retiré de la requête si possible.)

Je sais comment le faire pour les 3 affectations en utilisant le pivot avec simplement nommer les colonnes, il essaie de faire d'une manière dynamique que je n'ai pas trouvé une bonne solution pour l'instant. Je suis en train de le faire sur SQL Server 2005

EDIT

Idéalement je voudrais mettre en œuvre cela sans l'aide dynamique SQL, comme cela est contraire à la politique. Si ce n'est pas possible ... alors un exemple de travail avec Dynamic SQL fonctionnera.

Répondre

11

Je sais que vous avez dit pas SQL dynamique, mais je ne vois aucun moyen de le faire en ligne droite SQL.

Si vous consultez mes réponses à des problèmes similaires à Pivot Table and Concatenate Columns et PIVOT in sql 2005

La dynamique SQL il n'y a pas vulnérable à l'injection, et il n'y a aucune raison de l'interdire. Une autre possibilité (si les données changent très rarement) est de générer du code - au lieu de SQL dynamique, le SQL est généré pour une procédure stockée sur une base régulière.

+0

Cade grand exemple ressemble à ce que je vais devoir faire cette route ... –

+0

Merci pour le lien de référence et l'exemple! Je vais juste devoir aller à ce sujet de cette façon, SQL dynamique semble juste si sale, mais parfois nécessaire –

+0

Cade, je voulais juste dire encore merci! J'ai ce travail comme sur des roulettes maintenant sur mon côté .... –

1

La seule façon que j'ai trouvé pour faire cela est d'utiliser SQL dynamique et mettre les étiquettes de colonne dans une variable.

0

Vous pouvez interroger le schéma d'informations pour obtenir les noms et les types de colonne, puis utiliser le résultat comme sous-requête lorsque vous générez votre jeu de résultats. Notez que vous devrez probablement modifier un peu l'accès à la connexion.

+0

soin d'afficher un exemple? La seule façon dont j'ai trouvé ws pour construire la liste en utilisant SQL dynamique, et je ne préfère pas –

+0

Je ne suis pas sûr que vous serez en mesure de s'éloigner du SQL dynamique parce que la clause IN de PIVOT doit avoir des valeurs codées en dur ... aucune sous-sélection n'y est autorisée. Oh, comme je souhaite que ce n'était pas vrai! – BoltBait

0

C'est le même que PIVOT in sql 2005

Si ces données pour la consommation dans un rapport que vous pouvez utiliser une matrice de SSRS. Il va générer des colonnes dynamiquement à partir du jeu de résultats. Je l'ai utilisé plusieurs fois - cela fonctionne plutôt bien pour les rapports de tableaux croisés dynamiques.

Voici un bon exemple avec SQL dynamique. http://www.simple-talk.com/community/blogs/andras/archive/2007/09/14/37265.aspx

+0

C'est un scénario différent, je dois garder l'ordre ... –

-2
select studentname,[Assign1],[Assign2],[Assign3],[Total] 
from 
(
select studentname, assignname, grade from student 
)s 
pivot(sum(Grade) for assignname IN([Assign1],[Assign2],[Assign3],[Total])) as pvt 
+1

Veuillez ajouter une explication à votre réponse –

-1
SELECT TrnType 
INTO #Temp1 
FROM 
(
    SELECT '[' + CAST(TransactionType AS VARCHAR(4)) + ']' AS TrnType FROM tblPaymentTransactionTypes 
) AS tbl1 

SELECT * FROM #Temp1 

SELECT * FROM 
(
    SELECT FirstName + ' ' + LastName AS Patient, TransactionType, ISNULL(PostedAmount, 0) AS PostedAmount 
    FROM tblPaymentTransactions 
      INNER JOIN emr_PatientDetails ON tblPaymentTransactions.PracticeID = emr_PatientDetails.PracticeId 
      INNER JOIN tblPaymentTransactionDetails ON emr_PatientDetails.PatientId = tblPaymentTransactionDetails.PatientID 
         AND tblPaymentTransactions.TransactionID = tblPaymentTransactionDetails.TransactionID 
    WHERE emr_PatientDetails.PracticeID = 152 
) tbl 
PIVOT (SUM(PostedAmount) FOR [TransactionType] IN (SELECT * FROM #Temp1) 
) AS tbl4 
+0

cette réponse a besoin d'une signalisation significative pour aller avec le code, ou la traduction dans le domaine indiqué de la question. 'tblPaymentTransactionTypes' est clairement collé à partir de code non lié. – chris

6

Pour PIVOT ces données en utilisant SQL dynamique, vous pouvez utiliser le code suivant dans SQL Server 2005+:

Créer une table:

CREATE TABLE yourtable 
    ([StudentName] varchar(8), [AssignmentName] varchar(12), [Grade] int) 
; 

INSERT INTO yourtable 
    ([StudentName], [AssignmentName], [Grade]) 
VALUES 
    ('StudentA', 'Assignment 1', 100), 
    ('StudentA', 'Assignment 2', 80), 
    ('StudentA', 'Total', 180), 
    ('StudentB', 'Assignment 1', 100), 
    ('StudentB', 'Assignment 2', 80), 
    ('StudentB', 'Assignment 3', 100), 
    ('StudentB', 'Total', 280) 
; 

PIVOT dynamique :

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

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(AssignmentName) 
        from yourtable 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT StudentName, ' + @cols + ' from 
      (
       select StudentName, AssignmentName, grade 
       from yourtable 
      ) x 
      pivot 
      (
       min(grade) 
       for assignmentname in (' + @cols + ') 
      ) p ' 

execute(@query) 

Voir SQL Fiddle with Demo

Le résultat est:

| STUDENTNAME | ASSIGNMENT 1 | ASSIGNMENT 2 | ASSIGNMENT 3 | TOTAL | 
-------------------------------------------------------------------- 
| StudentA |   100 |   80 |  (null) | 180 | 
| StudentB |   100 |   80 |   100 | 280 | 
+0

Et si je devais remplacer null par zéro? – Chirag

+0

@Chirag [voir ma réponse ici] (http://stackoverflow.com/questions/15150068/sql-using-isnull-with-dynamic-pivot/15156448#15156448) – Taryn