PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Parte 2:como obter a soma de uma consulta baseada em partição sem realmente dinamizar


Use a solução que você tem (qualquer uma, prefiro a solução de array por razões óbvias), coloque-a em um CTE e use UNION para calcular os totais:
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;

Funções agregadas como count() ignore NULL valores, por isso só contará linhas onde existe um idioma.

Os tipos de dados de todas as colunas nas consultas de um UNION precisam corresponder, portanto, você não pode retornar valores inteiros em uma coluna na segunda consulta se a primeira consulta definir essa coluna como texto (ou varchar). É por isso que o resultado do count() precisa ser convertido em text

Os aliases de coluna na segunda consulta não são realmente necessários, mas os adicionei para mostrar como as listas de colunas devem corresponder