按月生成活跃员工的历史计数

问题描述 投票:0回答:1

我是一名 SQL 新手,一段时间以来一直在尝试寻找解决方案,但无济于事。如果解决方案嵌套在我错过的论坛中的某个位置,我深表歉意。

我有这样的疑问:

Select ID, Start Dt, End Dt
From Employees

产生以下结果:

身份证 开始Dt 结束Dt
1 2023 年 1 月 1 日 2023 年 2 月 3 日
2 2023 年 2 月 1 日 2023 年 3 月 10 日
3 2023 年 3 月 1 日 2023 年 4 月 21 日
4 2023 年 4 月 1 日 2023 年 5 月 15 日
5 2023 年 5 月 1 日 2023 年 6 月 3 日

我想对此进行转换,以便我可以按月生成活跃员工的计数(活跃定义为月/年位于“开始 Dt”和“结束 Dt”之间)。我希望它看起来像这样:

日期
2023 年 6 月 1
2023 年 5 月 2
2023 年 4 月 3
2023 年 3 月 2
2023 年 2 月 2
2023 年 1 月 1

我对如何实现这一目标有什么想法吗?我最大的问题是找到一种方法来创建与我拥有的数据分开的日期列,然后使用 BETWEEN 函数将该日期列连接到“Start Dt”和“End Dt”。

我尝试创建一个日期列并将其连接到员工表,如下所示:

Select distinct Dt, count(ID) over (order by Dt)
from Employees
inner join (select trunc (SYSDATE - ROWNUM) Dt
            from dual 
            connect by rownum < 365) dt on dt between Employees.Start_Dt and Employees.End_Dt

但是我似乎遗漏了一些东西,因为有多个重复的行并且计数没有相加。我的做法不对吗?

oracle-sqldeveloper
1个回答
0
投票

您计算的是每天的员工人数,而不是每月的人数;你不能只是将这些相加,因为这样你就会在一个月内超过一天的时间里得到重复的任何人。您也只能回顾 365 天,因此无法达到 2023 年 1 月的数据。

如果您生成一系列月份,作为您想要报告的任何期间的每个月的第一天(我使用了从今天算起的 18 个月;您可能需要从今年年初算起的 12 个月,或者其他的东西):

select add_months(trunc(sysdate, 'MM'), 1 - rownum)
from dual 
connect by rownum <= 18
order by 1
ADD_MONTHS(TRUNC(SYSDATE,'MM'),1-ROWNUM)
22 年 9 月 1 日
22 年 10 月 1 日
22 年 11 月 1 日
22 年 12 月 1 日
23 年 1 月 1 日
23 年 2 月 1 日
23 年 3 月 1 日
23 年 4 月 1 日
23 年 5 月 1 日
23 年 6 月 1 日
23 年 7 月 1 日
23 年 8 月 1 日
23 年 9 月 1 日
23 年 10 月 1 日
23 年 11 月 1 日
23 年 12 月 1 日
24 年 1 月 1 日
24 年 2 月 1 日

然后您可以在一系列日期加入,查找在该月月底之前(或者从技术上讲,在下个月开始之前)开始工作并在该月开始之后结束的员工:

select to_char(d.dt, 'FMMonth YYYY', 'nls_language=english') as "Month",
  count(e.id) as "Count"
from (
  select add_months(trunc(sysdate, 'MM'), 1 - rownum) as dt
  from dual 
  connect by rownum <= 18
) d
join employees e
  on e.start_dt < add_months(d.dt, 1)
  and e.end_dt >= d.dt
group by d.dt
order by d.dt desc
2023 年 6 月 1
2023 年 5 月 2
2023 年 4 月 2
2023 年 3 月 3
2023 年 2 月 2
2023 年 1 月 1

如果您想包括还没有结束日期的员工,您可以为此添加一个条款 - 我从 2023 年 12 月 15 日开始添加了一名额外的开放式员工:

select to_char(d.dt, 'FMMonth YYYY', 'nls_language=english') as "Month",
  count(e.id) as "Count"
from (
  select add_months(trunc(sysdate, 'MM'), 1 - rownum) as dt
  from dual 
  connect by rownum <= 24
) d
join employees e
  on e.start_dt < add_months(d.dt, 1)
  and (e.end_dt is null or e.end_dt >= d.dt)
group by d.dt
order by d.dt desc
2024 年 2 月 1
2024 年 1 月 1
2023 年 12 月 1
2023 年 6 月 1
2023 年 5 月 2
2023 年 4 月 2
2023 年 3 月 3
2023 年 2 月 2
2023 年 1 月 1

如果您想显示没有活跃员工的月份(这似乎不太可能,但为了以防万一并匹配您有限的样本数据),您可以将其设为外部联接:

select to_char(d.dt, 'FMMonth YYYY', 'nls_language=english') as "Month",
  count(e.id) as "Count"
from (
  select add_months(trunc(sysdate, 'MM'), 1 - rownum) as dt
  from dual 
  connect by rownum <= 24
) d
left join employees e
  on e.start_dt < add_months(d.dt, 1)
  and (e.end_dt is null or e.end_dt >= d.dt)
group by d.dt
order by d.dt desc
2024 年 2 月 1
2024 年 1 月 1
2023 年 12 月 1
2023 年 11 月 0
2023 年 10 月 0
2023 年 9 月 0
2023 年 8 月 0
2023 年 7 月 0
2023 年 6 月 1
2023 年 5 月 2
2023 年 4 月 2
2023 年 3 月 3
2023 年 2 月 2
2023 年 1 月 1
2022 年 12 月 0
2022 年 11 月 0
2022 年 10 月 0
2022 年 9 月 0

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.