Oracle中的累计计数不同

时间:2016-03-14 14:33:37

标签: sql oracle count distinct

我需要累计数周的客户数。没有制作子查询,有没有很好的方法呢?

我一直在寻找一些分析功能,但没有发现任何有价值的东西。所有工作解决方案都使用子查询或总计数,这对我的任务来说是错误的。

例如,对于这些表

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                   |
+----------------------------------+

3 个答案:

答案 0 :(得分:0)

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;

答案 1 :(得分:0)

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

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 :(得分:0)

大家谢谢。这是我要求的工作查询:

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