Gunakan solusi yang Anda miliki (salah satunya, saya lebih suka solusi array karena alasan yang jelas), masukkan ke dalam CTE, lalu gunakan UNION untuk menghitung total:
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;
Fungsi agregat seperti count()
abaikan NULL
nilai, jadi itu hanya akan menghitung baris di mana bahasa ada.
Tipe data semua kolom dalam kueri UNION harus cocok, jadi Anda tidak bisa mengembalikan nilai integer dalam kolom di kueri kedua jika kueri pertama mendefinisikan kolom itu sebagai teks (atau varchar). Itu sebabnya hasil dari count()
perlu ditransmisikan ke text
Alias kolom dalam kueri kedua tidak terlalu diperlukan, tetapi saya telah menambahkannya untuk menunjukkan bagaimana daftar kolom harus cocok