拆分列中的年度总和

时间:2017-11-05 23:24:07

标签: sql postgresql

我有两张桌子,我试图按年份计算学生互动的数量,然后在各自的年份加总。我附加的代码有效,但我想知道我是否忽略了更简单的计算方法。例如,如果我想这样做超过2年,我会诅咒自己这样做。

select      s.id
        , coalesce(cl2016.cl2016, 0) + coalesce(wf2016.wf2016, 0) as s2016
        , coalesce(cl2017.cl2017, 0) + coalesce(wf2017.wf2017, 0) as s2017
from        students s
left join   (
        select      dm.student_id
                , count(dm.meeting_id) as cl2016
        from        dim_meetings dm
        where       dm.start_time between '2016-01-01' and '2016-12-31'
        group by    dm.student_id
        ) cl2016 on cl2016.student_id = s.id
left join   (
        select      dm.student_id
                , count(dm.meeting_id) as cl2017
        from        dim_meetings dm
        where       dm.start_time between '2017-01-01' and '2017-12-31'
        group by    dm.student_id
        ) cl2017 on cl2017.student_id = s.id
left join   (
        select      sub.student_id
                , count(sub.id) as wf2016
        from        submissions sub
        where       sub.submitted_at between '2016-01-01' and '2016-12-31'
        group by    sub.student_id
        ) wf2016 on wf2016.student_id = s.id
left join   (
        select      sub.student_id
                , count(sub.id) as wf2017
        from        submissions sub
        where       sub.submitted_at between '2017-01-01' and '2017-12-31'
        group by    sub.student_id
        ) wf2017 on wf2017.student_id = s.id

2 个答案:

答案 0 :(得分:0)

使用条件聚合:

select s.id, dm.cl2016, cl2017, su.wf2016, su.wf2017,
       coalesce(dm.cl2016, 0) + coalesce(su.wf2016, 0) as s2016,
       coalesce(dm.cl2017, 0) + coalesce(su.wf2017, 0) as s2017
from students s left join
     (select dm.student_id,
             sum( (dm.start_time between '2016-01-01' and '2016-12-31')::int)  as cl2016,
             sum( (dm.start_time between '2017-01-01' and '2017-12-31')::int)  as cl2017
      from dim_meetings dm
      where dm.start_time between '2016-01-01' and '2017-12-31'
      group by dm.student_id
     ) dm
     on dm.student_id = s.id left join
     (select su.student_id,
             sum( (su.start_time between '2016-01-01' and '2016-12-31')::int)  as wf2016,
             sum( (su.start_time between '2017-01-01' and '2017-12-31')::int)  as wf2017
      from submissions su
      where su.start_time between '2016-01-01' and '2017-12-31'
      group by su.student_id
     ) su
     on su.student_id = s.id ;

答案 1 :(得分:0)

case expression置于聚合函数中非常有用,如下例所示:

select
        dm.student_id
      , count(dm.start_time '2016-01-01' 
        and < dm.start_time '2017-01-01' then dm.meeting_id end) as cl2016
      , count(dm.start_time '2017-01-01' 
        and < dm.start_time '2018-01-01' then dm.meeting_id end) as cl2017
from dim_meetings dm
where dm.start_time between '2016-01-01' and dm.start_time < '2018-01-01'  
group by dm.student_id
;

case expression返回一个值,然后该值在聚合函数中使用,就像在任何其他值中一样。

请注意&#34;&#34;对于日期范围来说是邪恶的,而是通过>=<使用显式范围,如上所示,其中包括将上边界日期向上移动到the next day。参见:

Bad habits to kick : mis-handling date / range queries

What do BETWEEN and the devil have in common?