Reputation: 667
I am trying to write a SQL which will give me the count of users who's status changed over the period of week over week.
For e.g. User_id 1 has a status of 1 on week_end_dt
of '2020-01-04' and then the status changed to 0 for the next week_end_dt
.
So for the first week all the 4 user's had status 1, hence the count would be 4. For the next week, except for user 3 rest changed their status, hence the count would be 1. So on and so forth.
Output
week_end_dt count_changed_0_1 count_change_1_0
2020-01-04 4 0
2020-01-11 1 0
2020-01-18 1 1
The last row (above) is because user 2 changed from 0 to 1 while user 3 changed from 1 to 0.
create table user_status (user_id int, week_end_dt date, status int);
insert into user_status values (1,'2020-01-04', 1);
insert into user_status values (1,'2020-01-11', 0);
insert into user_status values (1,'2020-01-18', 0);
insert into user_status values (1,'2020-01-25', 0);
insert into user_status values (1,'2020-02-01', 0);
insert into user_status values (2,'2020-01-04', 1);
insert into user_status values (2,'2020-01-11', 0);
insert into user_status values (2,'2020-01-18', 1);
insert into user_status values (2,'2020-01-25', 0);
insert into user_status values (2,'2020-02-01', 0);
insert into user_status values (3,'2020-01-04', 1);
insert into user_status values (3,'2020-01-11', 1);
insert into user_status values (3,'2020-01-18', 0);
insert into user_status values (3,'2020-01-25', 1);
insert into user_status values (3,'2020-02-01', 0);
insert into user_status values (3,'2020-02-08', 1);
insert into user_status values (3,'2020-02-15', 0);
insert into user_status values (3,'2020-02-22', 1);
insert into user_status values (4,'2020-01-04', 1);
insert into user_status values (4,'2020-01-11', 0);
insert into user_status values (4,'2020-01-18', 0);
insert into user_status values (4,'2020-01-25', 0);
insert into user_status values (4,'2020-02-01', 1);
Upvotes: 0
Views: 233
Reputation: 1270391
Assuming you have data for every week (no gaps) as in your sample data, you can use lag()
and aggregation like this:
select week_end_dt,
sum(case when prev_status = status then 0 else 1 end) as num_changes
from (select us.*, lag(status) over (partition by user_id order by week_end_dt) as prev_status
from user_status us
) us
group by week_end_dt
order by week_end_dt;
Here is a db<>fiddle.
Upvotes: 2