Aggregate case when inside non aggregate query

2019-07-21 05:21发布

问题:

I have a pretty massive query that in its simplest form looks like this:

select r.rep_id, u.user_id, u.signup_date, pi.application_date, pi.management_date, aum
from table1 r
left join table2 u on r.user_id=u.user_id
left join table3 pi on u.user_id=pi.user_id

I need to add one more condition that gives me count of users with non null application date per rep (like: rep 1 has 3 users with filled application dates), and assign it into categories (since 3 users, rep is a certain status category). This looks something like this:

case when sum(case when application_date is not null then 1 else 0 end) >=10 then 'status1'
   when sum(case when application_date is not null then 1 else 0 end) >=5 then 'status2'
   when sum(case when application_date is not null then 1 else 0 end) >=1  then 'status3'
   else 'no_status' end as category

However, if I was to simply add it to the select statement, all reps will becomes of status1 because the sum() is done over all advisors with application dates filled:

select r.rep_id, u.user_id, u.signup_date, pi.application_date, pi.management_date, aum,
(
 select case when sum(case when application_date is not null then 1 else 0 end) >=10 then 'status1'
   when sum(case when application_date is not null then 1 else 0 end) >=5 then 'status2'
   when sum(case when application_date is not null then 1 else 0 end) >=1  then 'status3'
   else 'no_status' end as category
from table3
) as category
from table1 r
left join table2 u on r.user_id=u.user_id
left join table3 pi on u.user_id=pi.user_id

Can you assist with having the addition to my query to be across reps and not overall? Much appreciated!

回答1:

Based on your description, I think you need a window function:

select r.rep_id, u.user_id, u.signup_date, pi.application_date, pi.management_date, aum,
       count(pi.application_date) over (partition by r.rep_id) as newcol
from table1 r left join
     table2 u
     on r.user_id = u.user_id left join
     table3 pi
     on u.user_id = pi.user_id;

You can use the count() in a case to get ranges, if that is what you prefer.