第2部分:如何获取基于分区的查询的总和而不实际转动

时间:2018-05-30 13:12:17

标签: sql postgresql postgresql-9.3

因为我没有最新版本的Postgresql(我有Postgresql 9.3),所以我不可能想出一个类似于计算特定字段总值的pivot函数的函数。

您可以单击下面的链接以使用我创建的问题作为参考,它们在代码中类似但在要求方面有所不同,但是有第二个查询使用数组并且还产生完全相同的结果。

How to create columns for different fields without applying the pivoting function

我目前得到以下结果

Current output

我想要这些结果

enter image description here

下面我有一个查询,它返回了我在3个不同栏目中讲的语言......我的问题是我无法想出一个可以让我得到的总和的解决方案很多学生说一种语言1,说多少语言2,说多少语言3

with t as (
  SELECT s.studentnumber as studentnr, p.firstname AS name, 
sl.gradenumber as gradenumber, l.text as language,
  dense_rank() over (partition by s.studentnumber, 
p.firstname, sl.gradenumber order by l.text) as seqnum

  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
 )
select studentnr, name, gradenumber,
   max(case when seqnum = 1 then language end) as language_1,
   max(case when seqnum = 2 then language end) as language_2,
   max(case when seqnum = 3 then language end) as language_3
from t
group by studentnr, name, gradenumber;

我问这个问题,因为如果没有办法做到这一点,那么如果不可能,我就不需要进一步研究它。

分区和密集的整个概念对我来说相对较新,我不确定它们产生进一步结果的程度和能力。

1 个答案:

答案 0 :(得分:1)

使用您拥有的解决方案(其中一个,我更喜欢阵列解决方案,原因很明显),将其放入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()忽略NULL值,因此它只计算语言所在的行。

UNION查询中所有列的数据类型必须匹配,因此如果第一个查询将该列定义为text(或varchar),则不能在第二个查询的列中返回整数值。这就是count()的结果需要转换为text

的原因

第二个查询中的列别名不是必需的,但我添加了它们以显示列列表必须匹配