繁体   English   中英

每月YTD的唯一计数

[英]Unique Count of YTD per month

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

表格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

在第1个月中,只有A有收入,因此计数为1;在第2个月, A和C截止到现在为止有收入,因此计数为2,最后在第3个月, A,B,C和D在当月有收入或之前的几个月( C在第2个月有收入,但第3个月没有收入),因此计数为4。

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

谢谢您的帮助

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

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()枚举每位员工的月份,将收入row_number()员工放在首位。 因此,如果有一个月的收入,则优先。

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

我采用的方法稍有不同,仍然在内联视图中使用分析函数的集合,但是坚持使用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

在这种情况下,我将使用复合表表达式从您的表中提取不同的月份,然后使用COUNT(DISTINCT来使用适当的联接条件对不同的雇员进行计数。换句话说:

WITH cteMonths AS (SELECT DISTINCT MONTH
                     FROM TABLE1)
SELECT m.MONTH, COUNT(DISTINCT t1.EMPLOYEE)
  FROM cteMonths m
  INNER JOIN TABLE1 t1
    ON t1.MONTH <= m.MONTH AND
       t1.REVENUE IS NOT NULL
  GROUP BY m.MONTH
  ORDER BY m.MONTH;

SQLFiddle在这里

祝你好运。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM