使用您拥有的解决方案(任一解决方案,由于显而易见的原因,我更喜欢数组解决方案),将其放入 CTE 中,然后使用 UNION 计算总数:
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;
聚合函数如count()
ignore NULL
值,因此它只会计算存在某种语言的行。
UNION 查询中所有列的数据类型必须匹配,因此如果第一个查询将该列定义为文本(或 varchar),则无法在第二个查询中返回该列中的整数值。这就是为什么结果是count()
需要投射到text
第二个查询中的列别名并不是真正必要的,但我添加了它们以显示列列表必须如何匹配