我应该在Postgres中使用GROUPING SETS,CUBE还是ROLLUP

时间:2019-02-07 18:14:36

标签: postgresql

我们上个月刚刚将其升级到Postgres 10,所以我对它的一些功能是陌生的。

因此该查询要求我显示每个学生受到照料的天数,并要求每个工作日有多少学生受到照料的总和

select distinct s.studentnr,(CASE When lower(cd.weekday) like lower('MONDAY') 
      then 1 else 0 end) as MONDAY,
          (CASE When lower(cd.weekday) like lower('TUESDAY') 
      then 1 else 0 end) as TUESDAY,
     (CASE When lower(cd.weekday) like lower('WEDNESDAY') 
      then 1 else 0 end) as WEDNESDAY,
     (CASE When lower(cd.weekday) like lower('THURSDAY') 
      then 1 else 0 end) as THURSDAY,
     (CASE When lower(cd.weekday) like lower('FRIDAY') 
      then 1 else 0 end) as FRIDAY,
scp.durationid

from student s

full join studentcarepreference scp on s.id = scp.studentid

full join careday cd on cd.studentcarepreferenceid = scp.id
 join pupil per on per.id = s.personid

 join studentschool ss ON ss.studentid = s.id 
 join duration d on d.id = sdc.durationid 
      AND d.id BETWEEN ss.validfrom AND ss.validuntil

where sdc.durationid = 1507
and cd.weekday is not null
order by s.studentnr

其中s.studentnr和cd.weekday均为varchar类型

导致

enter image description here

但是,我需要以下数据如下。

必填结果

enter image description here

哪种方法最适合在这种查询中使用?

更改代码后的新结果

select case grouping(studentnr)
         when 0 then studentnr
         else count(distinct studentnr)|| ' students'
       end studentnr
     , count(case lower(cd.weekday) when 'monday' then 1 end) monday
     , count(case lower(cd.weekday) when 'tuesday' then 1 end) teusday
     , count(case lower(cd.weekday) when 'wednesday' then 1 end) wednesday
     , count(case lower(cd.weekday) when 'thursday' then 1 end) thursday
     , count(case lower(cd.weekday) when 'friday' then 1 end) friday

  from mydata
 group by rollup ((studentnr))

按学生顺序排序

enter image description here

我猜几乎在那儿,只是结果或值是错误的。您会建议我考虑些什么以纠正结果?

1 个答案:

答案 0 :(得分:1)

您似乎想使用ROLLUP GROUPING SET来存储数据:

select case grouping(studentnr)
         when 0 then studentnr
         else count(distinct studentnr)|| ' students'
       end studentnr
     , count(distinct case careday when 'monday' then studentnr end) monday
     , count(distinct case careday when 'tuesday' then studentnr end) teusday
     , count(distinct case careday when 'wednesday' then studentnr end) wednesday
     , count(distinct case careday when 'thursday' then studentnr end) thursday
     , count(distinct case careday when 'friday' then studentnr end) friday
     , durationid
  from yourdata
 group by rollup ((studentnr, durationid))

哪个会产生预期的结果:

|  studentnr | monday | teusday | wednesday | thursday | friday | durationid |
|------------|--------|---------|-----------|----------|--------|------------|
|      10177 |      1 |       1 |         1 |        1 |      1 |       1507 |
|     717208 |      1 |       1 |         1 |        1 |      1 |       1507 |
|     722301 |      1 |       1 |         1 |        1 |      0 |       1507 |
| 3 students |      3 |       3 |         3 |        3 |      2 |     (null) |

ROLLUP中的第二组括号表示在进行汇总时应将studentnrdurationid汇总在同一级别。

仅使用一个摘要级别,ROLLUPCUBE之间并没有太大区别,但是使用GROUPING SETS将需要对GROUP BY子句进行一些更改以获得最低的所需细节水平。以下所有三个GROUP BY语句产生相同的结果:

 group by rollup ((studentnr, durationid))
 group by cube ((studentnr, durationid))
 group by grouping sets ((),(studentnr, durationid))