进行sql查询以生成累积订户的最简单方法是什么?

7xzttuei  于 2021-07-24  发布在  Java
关注(0)|答案(2)|浏览(433)

我有一个 subscriptions 带有列的表(在postgresql中) subscribed_at 以及 unsubscribed_at . 我想编写一个简单的查询,生成每个月底的累计订户计数列表(订阅减去截至该日期的未订阅)。
每一行基本上都是在查询:如果groupubymonth是“一月-2020”,那么有多少订阅 subscribed_at 日期为2020年1月或之前的一个月,以及 unsubscribed_at 无效日期或2020年1月之后。
我只是对sql不够熟悉,不知道这里的正确语法。
任何帮助都将不胜感激!
table

  1. +----+------+---------------+-----------------+
  2. | id | name | subscribed_at | unsubscribed_at |
  3. +----+------+---------------+-----------------+
  4. | 1 | John | '2020-01-08' | null |
  5. | 2 | Mary | '2020-01-09' | '2020-01-20' |
  6. | 3 | Jeff | '2020-01-10' | null |
  7. | 4 | Bill | '2020-02-02' | null |
  8. | 5 | Bob | '2020-02-08 | '2020-02-21' |
  9. +----+------+---------------+-----------------+

查询

  1. SELECT DATE_TRUNC('month', subscribed_at) as month,
  2. COUNT(*) as subscribers
  3. FROM subscriptions
  4. GROUP BY 1
  5. ORDER BY 1

期望输出

  1. +---------------+-------------+
  2. | month | subscribers |
  3. +---------------+-------------+
  4. | January 2020 | 2 |
  5. | February 2020 | 3 |
  6. +---------------+-------------+

哪里 subscribers 是该月底的累计净订户数。
下面是一个处理数据和查询的sqlfiddle:http://www.sqlfiddle.com/#!15/cd7725/1号文件

amrnrhlw

amrnrhlw1#

你可以用 generate_series() 枚举从第一个订阅开始到最后一个订阅结束之间的所有月份,然后横向联接以计算活动订阅计数。

  1. select d.dt, n.no_active_subscriptions
  2. from (
  3. select generate_series(
  4. date_trunc('month', min(subscribed_at)),
  5. date_trunc('month', max(unsubsribed_at)),
  6. interval '1 month'
  7. ) dt
  8. from subscriptions
  9. ) d
  10. cross join lateral (
  11. select count(*) no_active_subscriptions
  12. from subscriptions s
  13. where
  14. s.subscribed_at < d.dt + interval '1 month'
  15. and (s.unsubscribed_at >= d.dt or s.unsubscribed_at is null)
  16. ) n
展开查看全部
8dtrkrch

8dtrkrch2#

这里有一个方法。计算某人开始的日期+1和停止的日期-1。然后做一个累加。
在月末,记录每月的最后一条记录:

  1. with s as (
  2. select dte, sum(inc) ondate, sum(sum(inc)) over (order by dte) as subs
  3. from subscriptions s cross join lateral
  4. (values (subscribed_at, 1), (unsubscribed_at, -1)
  5. ) v(dte, inc)
  6. where v.dte is not null
  7. group by v.dte
  8. )
  9. select distinct on (date_trunc('month', dte)) *
  10. from s
  11. order by date_trunc('month', dte), dte desc;

这是一把小提琴。
这也许正是你想要的。或者你可能想调整一下。
停止计算的日期可能是停止后的第二天。如果是,则在子查询中添加一个日期。
如果要在每月的最后一天报告,可以使用表达式 (date_trunc('month', dte) + interval '1 month - 1 day')::date .

展开查看全部

相关问题