PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Partie 2 :comment obtenir la somme d'une requête basée sur une partition sans réellement pivoter

Utilisez la solution que vous avez (l'une ou l'autre, je préfère la solution matricielle pour des raisons évidentes), mettez-la dans un CTE, puis utilisez UNION pour calculer les totaux :

with students as (
  select studentnr, 
         name, 
         gradenumber, 
         languages[1] as language_1,
         languages[2] as language_2,
         languages[3] as language_3,
         languages[4] as language_4,
         languages[5] as language_5
  FROM (       
    SELECT s.studentnumber as studentnr, 
           p.firstname AS name,
           sl.gradenumber as gradenumber,
           array_agg(DISTINCT l.text) as languages
    FROM student s
        JOIN pupil p ON p.id = s.pupilid    
        JOIN pupillanguage pl on pl.pupilid = p.id
        JOIN language l on l.id = pl.languageid
        JOIN schoollevel sl ON sl.id = p.schoollevelid
    GROUP BY s.studentnumber, p.firstname
  ) t
)
select *
from students
union all
select null as studentnr,
       null as name, 
       null as gradenumber, 
       count(language_1)::text,
       count(language_2)::text, 
       count(language_3)::text, 
       count(language_4)::text, 
       count(language_5)::text
from students;

Fonctions d'agrégation comme count() ignorer NULL valeurs, il ne comptera donc que les lignes où une langue existe.

Les types de données de toutes les colonnes dans les requêtes d'un UNION doivent correspondre, vous ne pouvez donc pas renvoyer de valeurs entières dans une colonne de la deuxième requête si la première requête définit cette colonne comme texte (ou varchar). C'est pourquoi le résultat du count() doit être converti en text

Les alias de colonne dans la deuxième requête ne sont pas vraiment nécessaires, mais je les ai ajoutés pour montrer comment les listes de colonnes doivent correspondre