Моя основная цель - получить быстрое представление о среднем доходе для пользователей за период 30, 90, 180, 180+ дней. У меня есть электронное письмо, дата их присоединения к определенной группе и дата получения дохода
create temporary table cohorts (
email varchar(64)
, start_date timestamp
, purchase_date timestamp
, amount decimal(10,2)
)
;
insert into cohorts
values
('johnsmith@domain.com', '2020-01-01 00:00:00', '2020-01-01 12:00:00', '200.00')
, ('happyday@domain.com', '2020-01-01 00:00:00', '2020-02-28 00:00:00','100.00')
, ('happyday@domain.com', '2020-01-01 00:00:00', '2020-01-28 00:00:00','100.00')
, ('susieq@domain.com', '2020-01-01 00:00:00', '2020-05-01 00:00:00', '50.00')
, ('janedoe@domain.com', '2020-01-01 00:00:00', '2020-03-30 00:00:00', '75.00')
, ('janedoe@domain.com', '2020-01-01 00:00:00', '2020-07-30 00:00:00', '75.00')
;
Если бы я хотел увидеть средний доход пользователей за определенный период времени, я бы написал что-то вроде:
select
case
when datediff(day,start_date, purchase_date) < 30 then 'Within 30'
when datediff(day,start_date, purchase_date) < 90 then 'Within 90'
when datediff(day,start_date, purchase_date) < 180 then 'Within 180'
else 'Older than 180'
end as cohort_flag
, count(distinct email) num_of_emails
, sum(amount) summed_amt
, sum(amount)/count(distinct email) as avg_value
from cohorts
group by 1
cohort_flag num_of_emails summed_amt avg_value
Within 30 2 300.0 150.0
Within 90 2 175.0 87.5
Within 180 1 50.0 50.0
Older than 180 1 75.0 75.0
Однако, поскольку оператор case преобразуется в первое истинное предложение, он не включает доход от более ранних «когорт». Мой желаемый результат будет ниже, где пользователи в более ранних когортах являются частью других:
cohort_flag num_of_emails summed_amt avg_value
Within 30 2 300.0 150.0
Within 90 3 475.0 158.33
Within 180 4 525.0 131.25
Older than 180 4 600.0 150.0