Använd lösningen du har (antingen, jag föredrar arraylösningen av uppenbara skäl), lägg in den i en CTE och använd sedan UNION för att beräkna totalsummorna:
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;
Aggregera funktioner som count()
ignorera NULL
värden, så det kommer bara att räkna rader där ett språk finns.
Datatyperna för alla kolumner i frågorna i en UNION måste matcha, så du kan inte returnera heltalsvärden i en kolumn i den andra frågan om den första frågan definierar den kolumnen som text (eller varchar). Det är därför resultatet av count()
måste casta till text
Kolumnaliasen i den andra frågan är egentligen inte nödvändiga, men jag har lagt till dem för att visa hur kolumnlistorna måste matcha