Postgres简单的流失/保留

发布于 2025-02-14 01:36:10 字数 1725 浏览 0 评论 0 原文

我正在尝试创建一个简单的用户保留率,我尝试了很多搜索方式,但是它们似乎都没有高效,并且大多数都有很多我真正不需要的计算。

输入 我的桌子示例: https://dbfiddle.uk/?rdbms = postgres_14&; fiddle = ec68bebf63280023e828ebbb6cabd2d89 或:

DROP TABLE IF EXISTS users_churn;
create table 
users_churn(
id SERIAL PRIMARY KEY, 
users varchar(10) not null,
dates timestamp
);
insert into users_churn(users, dates)
values
('1ab7', '2022-01-04 10:22'),
('1ab7', '2022-04-26 18:30'),
('1ab7', '2022-05-12 20:10'),
('1ab7', '2022-07-02 20:55'),
('3ac5', '2022-02-05 05:12'),
('3ac5', '2022-04-09 07:17'),
('3ac5', '2022-07-03 04:19');
select * from users_churn

我期望的输出:

+-------------------------------------------------+
|                --DESIRED OUTPUT                 |
+-------------------------------------------------+
| ('1ab7', '2022-01-04 10:22', 'first_purchase'), |
| ('1ab7', '2022-02-01 00:00', 'churn'),          |
| ('1ab7', '2022-03-01 00:00', 'churn'),          |
| ('1ab7', '2022-04-26 18:30', 'retained'),       |
| ('1ab7', '2022-05-12 20:10', 'retained'),       |
| ('1ab7', '2022-06-01 00:00', 'churn'),          |
| ('1ab7', '2022-07-02 20:55', 'retained'),       |
| ('3ac5', '2022-02-05 05:12', 'first_purchase'), |
| ('3ac5', '2022-03-01 00:00', 'churn'),          |
| ('3ac5', '2022-04-09 07:17', 'retained'),       |
| ('3ac5', '2022-05-01 00:00', 'churn'),          |
| ('3ac5', '2022-06-01 00:00', 'churn'),          |
| ('3ac5', '2022-07-03 04:19', 'retained');       |
+-------------------------------------------------+

I'm trying to create a simple user retention, I tried a lot of ways searching, but none of them seems efficient and most of them have a lot of calculations that I don't really need.

Input
my table example:
https://dbfiddle.uk/?rdbms=postgres_14&fiddle=ec68bebf63280023e828ebb6cabd2d89
OR:

DROP TABLE IF EXISTS users_churn;
create table 
users_churn(
id SERIAL PRIMARY KEY, 
users varchar(10) not null,
dates timestamp
);
insert into users_churn(users, dates)
values
('1ab7', '2022-01-04 10:22'),
('1ab7', '2022-04-26 18:30'),
('1ab7', '2022-05-12 20:10'),
('1ab7', '2022-07-02 20:55'),
('3ac5', '2022-02-05 05:12'),
('3ac5', '2022-04-09 07:17'),
('3ac5', '2022-07-03 04:19');
select * from users_churn

Output that I expect:

+-------------------------------------------------+
|                --DESIRED OUTPUT                 |
+-------------------------------------------------+
| ('1ab7', '2022-01-04 10:22', 'first_purchase'), |
| ('1ab7', '2022-02-01 00:00', 'churn'),          |
| ('1ab7', '2022-03-01 00:00', 'churn'),          |
| ('1ab7', '2022-04-26 18:30', 'retained'),       |
| ('1ab7', '2022-05-12 20:10', 'retained'),       |
| ('1ab7', '2022-06-01 00:00', 'churn'),          |
| ('1ab7', '2022-07-02 20:55', 'retained'),       |
| ('3ac5', '2022-02-05 05:12', 'first_purchase'), |
| ('3ac5', '2022-03-01 00:00', 'churn'),          |
| ('3ac5', '2022-04-09 07:17', 'retained'),       |
| ('3ac5', '2022-05-01 00:00', 'churn'),          |
| ('3ac5', '2022-06-01 00:00', 'churn'),          |
| ('3ac5', '2022-07-03 04:19', 'retained');       |
+-------------------------------------------------+

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

傲鸠 2025-02-21 01:36:10

如果用户一个月内购买更多购买,您想做什么。此版本仅保留第一个版本。如果要保留所有购买,请摆脱 rn_month stuck:

with churn as (
  select c.users, 
         c.dates, 
         date_trunc('month', c.dates) as mdate,
         row_number() over (partition by c.users 
                                order by c.dates) as rn_all,
         row_number() over (partition by c.users, date_trunc('month', c.dates)
                                order by c.dates) as rn_month
    from users_churn c
), months as (
  select generate_series(
           min(c.mdate),
           current_date,
           interval '1 month'
         )::timestamp as mdate
    from churn c
)
select c.users,
       coalesce(c1.dates, m.mdate) as dates,
       case 
         when c1.rn_all = 1 then 'first_purchase'
         when c1.users is null then 'churn'
         else 'retained'
       end as status
  from churn c
       join months m 
         on m.mdate >= c.mdate 
        and c.rn_all = 1
       left join churn c1 
         on c1.users = c.users
        and c1.mdate = m.mdate
        and c.rn_month = 1
 order by c.users, m.mdate;

db<> fiddle 此处

It's not clear what you want done if there is more that one purchase by a user in a month. This version keeps only the first one. If you want to keep all purchases, then get rid of the rn_month stuff:

with churn as (
  select c.users, 
         c.dates, 
         date_trunc('month', c.dates) as mdate,
         row_number() over (partition by c.users 
                                order by c.dates) as rn_all,
         row_number() over (partition by c.users, date_trunc('month', c.dates)
                                order by c.dates) as rn_month
    from users_churn c
), months as (
  select generate_series(
           min(c.mdate),
           current_date,
           interval '1 month'
         )::timestamp as mdate
    from churn c
)
select c.users,
       coalesce(c1.dates, m.mdate) as dates,
       case 
         when c1.rn_all = 1 then 'first_purchase'
         when c1.users is null then 'churn'
         else 'retained'
       end as status
  from churn c
       join months m 
         on m.mdate >= c.mdate 
        and c.rn_all = 1
       left join churn c1 
         on c1.users = c.users
        and c1.mdate = m.mdate
        and c.rn_month = 1
 order by c.users, m.mdate;

db<>fiddle here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文