【问题标题】:Should I use GROUPING SETS, CUBE, or ROLLUP in Postgres我应该在 Postgres 中使用 GROUPING SETS、CUBE 还是 ROLLUP
【发布时间】:2019-02-07 18:14:35
【问题描述】:

我们上个月刚刚升级到 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 类型

导致

但是,我需要以下数据。

要求的结果

哪种方法最适合用于此类查询?

更改代码后的新结果

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))

按学生排序

我猜差不多了,只是结果或值是错误的。你会建议我研究什么来纠正结果?

【问题讨论】:

    标签: postgresql


    【解决方案1】:

    您似乎想使用GROUPING SET ROLLUP yourdata:

    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))
    

    【讨论】:

    • 如果您提供 Create Table 语句和以分隔文本格式或作为插入语句的适当示例数据而不是提供数据图片,那么我/我们可以提供更好的帮助。
    • 我已经编辑了我的回复,以计算每天的不同 studentnr 值,而不是非不同数字 1。此外,如果您不再在结果集中包含 durationid 值,则可以删除 group by 子句中的额外集或括号
    猜你喜欢
    • 2014-10-06
    • 2016-11-20
    • 1970-01-01
    • 1970-01-01
    • 2016-05-14
    • 2021-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多