【问题标题】:Cumulative count distinct in OracleOracle 中不同的累积计数
【发布时间】:2016-03-14 14:33:37
【问题描述】:

我需要数周累计客户数量。有什么好的方法可以在不进行子查询的情况下做到这一点?

我想寻找一些分析函数,但没有发现任何有价值的东西。所有可行的解决方案都使用子查询或总和,这对我的任务来说是错误的。

例如,对于这些表

WITH the_data as (  
   select sysdate - 28 dt, 1 val from dual union all  
   select sysdate - 27 dt, 13 val from dual union all  
   select sysdate - 20 dt, 15 val from dual union all  
   select sysdate - 19 dt, 1 cusval from dual union all  
   select sysdate - 18 dt, 2  from dual union all  
   select sysdate - 17 dt, 3  from dual union all  
   select sysdate - 16 dt, 4  from dual union all  
   select sysdate - 15 dt, 5  from dual union all  
   select sysdate - 14 dt, 6  from dual union all  
   select sysdate - 8 dt, 7  from dual union all  
   select sysdate - 6 dt, 8  from dual union all  
   select sysdate - 3 dt, 9  from dual union all  
   select sysdate - 2 dt, 9  from dual union all  
   select sysdate - 1 dt, 10  from dual)  

我想获得关注

+----------------------------------+
| WEEK_NUM    CUM_DISTINCT_COUNT   |
+----------------------------------+
| 8           2                    |
| 9           6                    |
| 10          8                    |
| 11          11                   |
| 12          12                   |
+----------------------------------+

【问题讨论】:

  • 您应该发布您的表结构、示例数据、您尝试过的内容以及期望的结果;没有这些信息,就很难回答。 Here你可以阅读如何提出一个好问题
  • 没有任何数据将很难为您提供帮助,但解决方案可能类似于COUNT(DISTINCT CUST_NUMBER) OVER (PARTITION BY WEEK)

标签: sql oracle count distinct


【解决方案1】:

您如何执行此操作取决于您的计数是否需要来自不同的客户。要显示一些正在运行的聚合选项:

WITH the_data as (
   select sysdate - 28 dt, 1 val from dual union all
   select sysdate - 27 dt, 13 val from dual union all
   select sysdate - 20 dt, 15 val from dual union all
   select sysdate - 19 dt, 1 cusval from dual union all
   select sysdate - 18 dt, 2  from dual union all
   select sysdate - 17 dt, 3  from dual union all
   select sysdate - 16 dt, 4  from dual union all
   select sysdate - 15 dt, 5  from dual union all
   select sysdate - 14 dt, 6  from dual union all
   select sysdate - 8 dt, 7  from dual union all
   select sysdate - 6 dt, 8  from dual union all
   select sysdate - 3 dt, 9  from dual union all
   select sysdate - 2 dt, 9  from dual union all
   select sysdate - 1 dt, 10  from dual)
select distinct trunc(dt,'WW') wk
      ,count(val) over (partition by trunc(dt,'WW')) as wk_cnt
      ,count(distinct val) over (partition by trunc(dt,'WW')) as wk_distinct_cnt
      ,count(val) over (order by trunc(dt,'WW')) as running_wk_cnt
--      ,count(distinct val) over (order by trunc(dt,'WW')) as running_distinct_wk_cnt
from the_data
order by trunc(dt,'WW')

returns
WK,         WK_CNT, WK_DISTINCT_CNT, RUNNING_WK_CNT
12/02/2016, 2,      2,               2
19/02/2016, 3,      3,               5
26/02/2016, 4,      4,               9
04/03/2016, 2,      2,               11
11/03/2016, 3,      2,               14

但是,如果您取消注释该行以执行运行不同计数,您将收到错误,因为完全使用此构造是不可能的。

【讨论】:

    【解决方案2】:
    SELECT DISTINCT
           TRUNC( date_column, 'WW' ) AS week_number,
           COUNT( customer_id ) OVER ( ORDER BY TRUNC( date_column, 'WW' ) ) AS num_customers
    FROM   your_table
    ORDER BY week_number
    

    要获得自 2016-01-01 以来不同客户的累积数量,您可以这样做:

    SELECT DISTINCT
           last_day_of_week,
           COUNT( is_first_instance_of_customer )
             OVER( ORDER BY last_day_of_week ) AS num_unique_customers
    FROM   (
      SELECT TRUNC( date_value, 'WW' ) + 6 AS last_day_of_week,
             CASE ROW_NUMBER()
                    OVER ( PARTITION BY customer_id
                           ORDER BY date_value )
             WHEN 1
             THEN 1
             END AS is_first_instance_of_customer
      FROM   your_table
    )
    ORDER BY last_day_of_week;
    

    【讨论】:

    • 谢谢,但这行不通。这就是我如何获得不同的 week_number 和 num_customers 对。但我需要 2016 年 1 月 1 日到每周最后一天之间的客户数量,加上我的表“your_table”包含 customer_id 的重复项
    • @Powerfool 更新了不同客户的累积计数。
    【解决方案3】:

    谢谢大家。这是我要求的有效查询:

    with dt as (  
    select 'A1' PLANT, '1' CUSTOMERID, date'2016-01-01' CALDAY from dual union all
    select 'A1' PLANT, '2' CUSTOMERID, date'2016-01-01' CALDAY from dual union all
    select 'A1' PLANT, '3' CUSTOMERID, date'2016-01-01' CALDAY from dual union all
    select 'A2' PLANT, '1' CUSTOMERID, date'2016-01-02' CALDAY from dual union all
    select 'A2' PLANT, '2' CUSTOMERID, date'2016-01-02' CALDAY from dual union all
    select 'A1' PLANT, '1' CUSTOMERID, date'2016-01-08' CALDAY from dual union all
    select 'A1' PLANT, '2' CUSTOMERID, date'2016-01-08' CALDAY from dual union all
    select 'A2' PLANT, '4' CUSTOMERID, date'2016-01-08' CALDAY from dual union all
    select 'A2' PLANT, '4' CUSTOMERID, date'2016-01-15' CALDAY from dual union all
    select 'A1' PLANT, '4' CUSTOMERID, date'2016-01-22' CALDAY from dual)
    
    
    , first_buys_plant as (
      select customerid, plant, calday from (
        select customerid, plant, calday, row_number() over (partition by customerid, plant order by calday) rn
        from dt
      ) where rn = 1
    )
    select plant, calweek, max(cum_num) cum_num_cust from (
      select 
        plant,
        to_char(calday, 'ww') calweek,
        count(customerid) over(partition by plant order by calday rows between unbounded preceding and current row) cum_num
      from first_buys_plant
    ) group by plant, calweek
    order by 1,2
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-02
      • 2014-07-26
      • 2018-12-04
      • 1970-01-01
      • 2017-03-23
      • 2020-10-08
      • 2021-10-29
      • 1970-01-01
      相关资源
      最近更新 更多