2014-09-07 10 views
2

Я пытаюсь найти количество активных подписчиков за месяц по шкале времени.Накопительный счет Postgres с течением времени

Таблица: Абонементы Поля:

  • ID
  • "CreationDate"
  • "deletionDate"

подписка считается активным при определенной меткой времени, когда:

  1. de letionDate является нулевым
  2. конкретный временной метки попадает между CreationDate и deletionDate

Пример:

  • Подписка А имеет CreationDate "2014-06-27 11: 37: 34.205 + 00" и deletionDate «2014 -08-01 04: 16: 34.435 + 00 ". Абонент А считается активным в июне 2014 года, в июле 2014 года и в августе 2014 года.
  • Подписки В имеет созданиеДата «2014-06-27 11: 37: 34.205 + 00» и «удаление» «2014-06-28 11: 37: 34.205 +00" . Подписка B активна только в июне 2014 года.
  • Подписчик C имеет дату создания «2014-06-27 11: 37: 34.205 + 00» и не удаляет дату. Подписка C считается активной в течение месяцев июня 2014 года и до текущего месяца.

Это то, что я пробовал:

select "Month", sum(sub) over (order by "Month" asc) as "Active subscriptions" 
from 
(select to_char(subscriptions."creationDate" at time zone '-7', 'YYYY-MM') as "Month", 
    count(distinct subscriptions.id) as sub 
    from subscriptions 
    where (to_char(subscriptions."deletionDate" at time zone '-7', 'YYYY-MM') is null 
     or to_char(subscriptions."deletionDate" at time zone '-7', 'YYYY-MM') >= to_char(subscriptions."creationDate" at time zone '-7', 'YYYY-MM')) 
    group by "Month") as foo 

Однако проблема с этим состоит в том, что он в том числе количество не-активных подписок в предыдущем месяце. Чтобы проиллюстрировать, что я имею в виду, мой запрос выше, как представляется, включает в себя подписку B (в примере выше) в качестве активной подписки в июле 2014 года.

Я не уверен, как получить мои «активные подписки» для определенного месяца для удаления количество подписей, которые больше не действуют в предыдущие месяцы.

Спасибо! :)

ответ

3
SELECT m, count(subscriptions.*) 
FROM subscriptions 
JOIN generate_series('2010-01-01'::date, now(), interval '1 mon') AS m 
ON m >= subscriptions.creationDate AND 
     (subscriptions.deletionDate IS NULL OR m <= subscriptions.deletionDate) 
/* You may get better indexed performance if you use a date 
    far in the future for current 
    accounts, instead of NULL. Then you can use BETWEEN */ 
GROUP BY m ORDER BY m; 
+1

Дата поддерживает «бесконечность», которая отвечает требованиям. http://www.postgresql.org/docs/current/static/datatype-datetime.html –

+0

Спасибо за вашу помощь! – christinang89

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