2015-11-23 2 views
0

У меня есть таблица paid_users, что выглядит следующим образом:Запрос, чтобы найти количество платящих клиентов и сбитых клиентов?

http://sqlfiddle.com/#!15/d25ba

Я пытаюсь определить платежеспособных клиентов, сгруппированных Месяц-Год и месили клиентов, сгруппированных Месяц-Год. По сути, есть плательщики и пользователи. Плательщик - это тот, кто платит за этого конкретного пользователя. Если нет payment_stop_date, это означает, что плательщик все еще платит за пользователя. Payment_stop_date указывает, если/когда плательщик прекратил платить за пользователя.

Я хочу, чтобы найти число платежеспособных клиентов, в которых результат запроса должен быть:

Month-Year | New Paying Customers | Churned Paying Customers 
------------------------------------------------------------ 
11-2014 | 1     | 
12-2014 |      | 1 
01-2015 | 1     | 
04-2015 |      | 
06-2015 | 2     | 
07-2015 | 1     | 
10-2015 |      | 1 

Глядя на payor_id 3453, она начала платить за user_id 3182 в 11-2014, так что она будет включена в группе 11-2014. Тем не менее, она перестала платить за двух пользователей в 12-2014 году, поэтому включена в эту группу с отбитыми 12-2014 годами. Плательщик считается взломанным платежным клиентом, если они полностью перестали платить нам (т. Е. Они могли платить за одного человека, а затем отменили его. Или в этом случае плательщик 3453 платил за 2 пользователей, а затем отменил их). Затем Payor_3453 начал платить за user_id 4716 в 01-2015, поэтому она включена в группу 01-2015.

Я с трудом пишу запрос для этого, поскольку это не обязательно различны payor_id поскольку payor_id 3453 считается новым платящий клиент дважды

ответ

1

Не уверен, что я понял, это право: на каждый месяц вы хотите знать, как много клиентов начали платить за своего первого пользователя и сколько клиентов перестали платить за своего последнего пользователя?

Решение кажется довольно сложным, но, возможно, все не так просто.

with months as 
(
    select * from 
    generate_series('2014-06-01', now() at time zone 'utc', interval '1 month') as month 
    cross join paid_users 
) 
, sums as 
(
    select month, payor_id, joiners, leavers, sum(net) over (partition by payor_id order by month) 
    from 
    (
     select month, payor_id, joiners, leavers, coalesce(joiners,0) - coalesce(leavers, 0) as net 
     from 
     (
      select payor_id, month, count(*) as joiners 
      from months 
      where payment_start_date >= month 
      and payment_start_date < month + interval '1 month' 
      group by month, payor_id 
     ) as t 
     full join 
     (
      select payor_id, month, count(*) as leavers 
      from months 
      where payment_stop_date >= month 
      and payment_stop_date < month + interval '1 month' 
      group by month, payor_id 
     ) as u 
     using (month, payor_id) 
    ) as v 
) 

select * from sums 
order by payor_id, sum 

выше должно дать вам полную платные пользователь для каждого клиента

 month  | payor_id | joiners | leavers | sum 
---------------------+----------+---------+---------+----- 
2014-06-01 00:00:00 |  1725 |  1 |   | 1 
2014-06-01 00:00:00 |  1929 |  1 |   | 1 
2015-10-01 00:00:00 |  1929 |   |  1 | 0 
2014-06-01 00:00:00 |  1986 |  1 |   | 1 
2014-11-01 00:00:00 |  3453 |  2 |   | 2 
2014-12-01 00:00:00 |  3453 |   |  2 | 0 
2015-01-01 00:00:00 |  3453 |  1 |   | 1 
2015-03-01 00:00:00 |  3453 |  1 |   | 2 
2015-04-01 00:00:00 |  3453 |  2 |  1 | 3 
2015-05-01 00:00:00 |  3453 |   |  1 | 2 
2015-06-01 00:00:00 |  3453 |   |  1 | 1 
2015-10-01 00:00:00 |  3453 |  1 |   | 2 
2015-07-01 00:00:00 |  6499 |  1 |   | 1 
2015-08-01 00:00:00 |  6499 |  3 |   | 4 
2015-10-01 00:00:00 |  6499 |   |  1 | 3 
2015-11-01 00:00:00 |  6499 |   |  1 | 2 

Настолько новые клиенты являются клиентами, которые идут от суммы 0 до ненулевой суммы, месил клиенты клиенты, которые достигают суммы 0?

select month, new, churned from 
(
    (
     select month, count(*) as churned 
     from sums 
     where sum = 0 
     group by month 
    ) as l 
    full join 
    (
     select month, count(*) as new 
     from (
      select month, payor_id, sum, coalesce(lag(sum) over (partition by payor_id order by month), 0) as prev_sum 
      from sums 
      order by payor_id, month 
     ) as t 
     where prev_sum = 0 and sum > 0 
     group by month 
    ) as r 
    using (month) 
) 
order by month 

Выходы

 month  | new | churned 
---------------------+-----+--------- 
2014-06-01 00:00:00 | 3 |   
2014-11-01 00:00:00 | 1 |   
2014-12-01 00:00:00 |  |  1 
2015-01-01 00:00:00 | 1 |   
2015-07-01 00:00:00 | 1 |   
2015-10-01 00:00:00 |  |  1 

Надежда это помогает. Если кто-то знает более простой способ, я был бы рад услышать об этом.

+0

Это кажется очень разумным, и вы определенно объяснили идею вопроса лучше меня - большое вам спасибо за помощь! Числа выглядят правильно, и логика имеет большой смысл :) –

Смежные вопросы