Annuler le pivot avec le nom de la colonne


127

J'ai une table StudentMarksavec des colonnes Name, Maths, Science, English. Les données sont comme

Name,  Maths, Science, English  
Tilak, 90,    40,      60  
Raj,   30,    20,      10

Je veux que cela soit arrangé comme suit:

Name,  Subject,  Marks
Tilak, Maths,    90
Tilak, Science,  40
Tilak, English,  60

Avec unpivot, je peux obtenir le nom, les marques correctement, mais je ne parviens pas à obtenir le nom de la colonne dans la table source dans la Subjectcolonne dans le jeu de résultats souhaité.

Comment puis-je atteindre cet objectif?

J'ai jusqu'à présent atteint la requête suivante (pour obtenir le nom, les marques)

select Name, Marks from studentmarks
Unpivot
(
  Marks for details in (Maths, Science, English)

) as UnPvt

1
Pouvez-vous publier ce que vous avez fait jusqu'à présent? requête / sortie.
Hart CO

Réponses:


204

Votre requête est très proche. Vous devriez pouvoir utiliser les éléments suivants, qui incluent le subjectdans la liste de sélection finale:

select u.name, u.subject, u.marks
from student s
unpivot
(
  marks
  for subject in (Maths, Science, English)
) u;

Voir SQL Fiddle avec démo


@bluefeet Existe-t-il un moyen pour que vous n'ayez pas besoin de spécifier les noms (mathématiques, sciences, anglais)? Je fais cette opération sur de nombreuses tables, toutes avec la même structure mais avec des noms de colonnes différents.
LBogaardt

1
@LBogaardt Non, vous devez définir explicitement les colonnes à inclure.
jjjjjjjjjjj

@LBogaardt Jetez un œil à ma réponse ici , vous pouvez utiliser le SQL dynamique pour annuler le pivot sans spécifier les noms de colonne.
Taryn

8

Vous pouvez également essayer la méthode standard de non-pivotement SQL en utilisant une séquence de logique avec le code suivant. Le code suivant comporte 3 étapes:

  1. créer plusieurs copies pour chaque ligne en utilisant la jointure croisée (créer également une colonne d'objet dans ce cas)
  2. créer la colonne "marques" et remplir les valeurs pertinentes en utilisant l'expression de cas (ex: si le sujet est de la science, choisir une valeur dans la colonne de la science)
  3. supprimer toutes les combinaisons nulles (si elle existe, l'expression de table peut être totalement évitée s'il n'y a strictement aucune valeur nulle dans la table de base)

     select *
     from 
     (
        select name, subject,
        case subject
        when 'Maths' then maths
        when 'Science' then science
        when 'English' then english
        end as Marks
    from studentmarks
    Cross Join (values('Maths'),('Science'),('English')) AS Subjct(Subject)
    )as D
    where marks is not null;

Cela fonctionne également avec n'importe quel SGBDR! VALUES, lorsqu'elles ne sont pas disponibles, peuvent être remplacées par une sous-requête avec SELECT ... UNION ... SELECT ... Vous vous demandez sur les performances de ce CROSS JOIN cependant ...
Cristi S.

0

SELECT * FROM étudiant

UNPIVOT (notes pour les matières en (mathématiques, sciences, anglais));


1
C'est déjà la même réponse que la réponse acceptée et hautement votée publiée il y a près de 6 ans?
ImaginaryHuman072889

0

Une autre façon d'utiliser la jointure croisée serait de spécifier les noms de colonne dans la jointure croisée

select name, Subject, Marks 
from studentmarks
Cross Join (
values (Maths,'Maths'),(Science,'Science'),(English,'English')
) un(Marks, Subject)
where marks is not null;
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.