postgresql - cumul. сумма активных клиентов по месяцам (без оттока) - PullRequest
0 голосов
/ 03 июля 2018

Я хочу создать запрос, чтобы получить совокупную сумму по месяцам наших активных клиентов. Хитрость заключается в том, что (к сожалению) некоторые клиенты оттока, и поэтому мне нужно удалить их из совокупной суммы за месяц, когда они покидают нас.

Вот пример таблицы моих клиентов:

customer_id |   begin_date  |   end_date
-----------------------------------------
1           |   15/09/2017  |   
2           |   15/09/2017  |   
3           |   19/09/2017  |   
4           |   23/09/2017  |   
5           |   27/09/2017  |   
6           |   28/09/2017  |   15/10/2017
7           |   29/09/2017  |   16/10/2017
8           |   04/10/2017  |   
9           |   04/10/2017  |   
10          |   05/10/2017  |   
11          |   07/10/2017  |   
12          |   09/10/2017  |   
13          |   11/10/2017  |   
14          |   12/10/2017  |   
15          |   14/10/2017  |

Вот чего я хочу достичь:

month   |   active customers
-----------------------------------------       
2017-09 |   7
2017-10 |   6

Мне удалось добиться этого с помощью следующего запроса ... Однако я хотел бы знать, есть ли лучший способ.

select 
    "begin_date" as "date",
    sum((new_customers.new_customers-COALESCE(churn_customers.churn_customers,0))) OVER (ORDER BY new_customers."begin_date") as active_customers
FROM (
    select 
        date_trunc('month',begin_date)::date as "begin_date",
        count(id) as new_customers
    from customers
    group by 1
) as new_customers
LEFT JOIN(
    select 
        date_trunc('month',end_date)::date as "end_date",
        count(id) as churn_customers
    from customers
    where
        end_date is not null
    group by 1
) as churn_customers on new_customers."begin_date" = churn_customers."end_date"
order by 1
;

1 Ответ

0 голосов
/ 03 июля 2018

Вы можете использовать CTE для вычисления общей суммы end_dates, а затем вычесть ее из числа дат начала, используя левое объединение

SQL Fiddle

Запрос 1 :

WITH edt
AS (
    SELECT to_char(end_date, 'yyyy-mm') AS mon
        ,count(*) AS ct
    FROM customers
    WHERE end_date IS NOT NULL
    GROUP BY to_char(end_date, 'yyyy-mm')
    )
SELECT to_char(c.begin_date, 'yyyy-mm') as month
    ,COUNT(*) - MAX(COALESCE(ct, 0)) AS active_customers
FROM customers c
LEFT JOIN edt ON to_char(c.begin_date, 'yyyy-mm') = edt.mon
GROUP BY to_char(begin_date, 'yyyy-mm')
ORDER BY month;

Результаты

|   month | active_customers |
|---------|------------------|
| 2017-09 |                7 |
| 2017-10 |                6 |
...