每月YTD的唯一计数

时间:2018-07-15 12:23:37

标签: sql oracle

我正在尝试为每个在本月或前几个月有任何收入的唯一雇员的年初至今计数

表1

Month       Employee    Revenue
01-04-18    A           867
01-04-18    B   
01-04-18    C   
01-04-18    D   
01-05-18    A           881
01-05-18    B   
01-05-18    C           712
01-05-18    D   
01-06-18    A           529
01-06-18    B           456
01-06-18    C   
01-06-18    D           878

预期产量

Month       Count
01-04-18    1
01-05-18    2
01-06-18    4

在第一个月中,只有 A 有任何收入,因此计数为1,在第二个月中, A&C 到目前为止有收入,因此计数为2,最后在第三个月 A,B,C和D 在当月或之前的几个月有收入( C 在第2个月有收入,但没有在第3个月),因此计数为4。

有什么办法可以得到这个结果?

谢谢您的帮助

3 个答案:

答案 0 :(得分:1)

这很棘手,因为您具有聚合和窗口功能。我会采用以下方法:将用户拥有收入的第一个月标记出来,然后使用该信息:

select month,
       sum(sum(case when seqnum = 1 and revenue is not null then 1 else 0 end)) over (order by month)
from (select t.*,
             row_number() over (partition by employee order by (case when revenue is not null then month end) nulls last) as seqnum
      from t
     ) t
group by month;

row_number()列举了每个雇员的月数,将收入最高的雇员放在首位。因此,如果有一个月的收入,则以第一个为准。

外部聚合然后对序列和收入是否不为null进行累积和检查。

答案 1 :(得分:0)

我采用的方法稍有不同,仍然在内联视图中使用分析函数的聚合,但是坚持使用count(),因为我认为意图稍有差异:

select month,
  count(has_revenue) as result
from (
  select month, employee,
    case when count(revenue)
      over (partition by employee order by month) > 0
        then employee end as has_revenue
  from table1
)
group by month

对于内联视图,每个月/员工的分析计数使用当前行之前的无界默认窗口,因此它将忽略未来几个月的任何行;并且仅在该计数为非零时给出非空响应。外部计数会忽略该生成的列表达式中的空值。

在CTE中使用示例数据进行演示:

with table1 (month, employee, revenue) as (
            select date '2018-04-01', 'A', 867 from dual
  union all select date '2018-04-01', 'B', null from dual
  union all select date '2018-04-01', 'C', null from dual
  union all select date '2018-04-01', 'D', null from dual
  union all select date '2018-05-01', 'A', 881 from dual
  union all select date '2018-05-01', 'B', null from dual
  union all select date '2018-05-01', 'C', 712 from dual
  union all select date '2018-05-01', 'D', null from dual
  union all select date '2018-06-01', 'A', 529 from dual
  union all select date '2018-06-01', 'B', 456 from dual
  union all select date '2018-06-01', 'C', null from dual
  union all select date '2018-06-01', 'D', 878 from dual
)
select month,
  count(has_revenue) as result
from (
  select month, employee,
    case when count(revenue)
      over (partition by employee order by month) > 0
        then employee end as has_revenue
  from table1
)
group by month
order by month;

MONTH          RESULT
---------- ----------
2018-04-01          1
2018-05-01          2
2018-06-01          4

这是数据集中所有行的累积值,但是您只显示了一年的数据。如果您的数据有多年,并且还没有过滤到一年,则将年份添加到分区中:

  select month, employee,
    case when count(revenue)
      over (partition by employee, trunc(month, 'YYYY') order by month) > 0
        then employee end as has_revenue
  from table1

答案 2 :(得分:0)

在这种情况下,我将使用复合表表达式从表中提取不同的月份,然后使用df$B <- ceiling(df$A/3) 使用适当的联接条件来计算不同的员工。或者,换句话说:

COUNT(DISTINCT

SQLFiddle here

好运。