【问题标题】:How to find the share of clients who "outflow" every month? (SQLite or Oracle)如何找到每个月“流出”的客户份额? (SQLite 或 Oracle)
【发布时间】:2021-02-28 03:50:06
【问题描述】:

CLIENTS 表包含银行客户的每月快照, 在给定月份进行过任何交易的人。属性:report_month 和client_id。我们假设客户在 N 月从银行“流出”,如果在 N 月 它处于活动状态(存在于 CLIENTS 表中)并且在 N + 1、N + 2、N + 3 个月内处于非活动状态。

如何找到每个月“流出”的客户份额?

表格如下:

report_month   client_id
2020-01-01     0023
2020-03-01     0125

...

【问题讨论】:

  • 请用您正在运行的数据库标记您的问题:mysql、oracle、sqlserver...?

标签: sql oracle sqlite datetime count


【解决方案1】:

您可以使用窗口函数和窗口框架来做到这一点。在标准 SQL 中,这看起来像:

select report_month, sum(case when cnt = 0 then 1 else 0 end) as outflow
from (
    select t.*,
        count(*) over(
            partition by client_id 
            order by report_month
            range between interval '1' month following and interval '3' month following
        ) cnt
    from mytable t
) t
group by report_month

这假定report_month 是类似日期的数据类型,并且每个客户每个report_month 都有0 或1 条记录。如果客户可能在一个月内出现多次,您可以将外部条件 sum() 更改为:

count(distinct case when cnt = 0 then client_id end) as outflow

在日期算术支持较差的 SQLite 中,它有点复杂。如果你能忍受大约一个月的时间,你可以这样做:

select report_month, sum(case when cnt = 0 then 1 else 0 end) as outflow
from (
    select t.*,
        count(*) over(
            partition by client_id 
            order by julianday(report_month)
            range between 28 following and 92 following
        ) cnt
    from mytable t
) t
group by report_month

【讨论】:

  • 是的,report_month 是日期,客户出现一次。但在这段代码中,我收到以下错误:“'1'”附近:语法错误。我在 sqlite 中尝试过
  • @GreenMr:你运行的是哪个版本的 SQLite?上面的代码很乐意在 Oracle 上运行,您也在问题中标记并提到了它。
  • SQLite 3.29。抱歉,我认为它们具有相同的功能 =(
  • @GreenMr:这就是为什么您应该始终只标记一个数据库,而不是更多...请参阅我的编辑以获取 SQLite 的替代方案。
  • 很抱歉这个问题,但你的 sqlite 代码中的 28 和 92 是什么意思? julianday 格式数据到 int 这样的 2458239.5
猜你喜欢
  • 1970-01-01
  • 2021-08-04
  • 2023-02-09
  • 1970-01-01
  • 2019-05-28
  • 1970-01-01
  • 1970-01-01
  • 2019-03-04
  • 1970-01-01
相关资源
最近更新 更多