我是一名 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
但是我似乎遗漏了一些东西,因为有多个重复的行并且计数没有相加。我的做法不对吗?
您计算的是每天的员工人数,而不是每月的人数;你不能只是将这些相加,因为这样你就会在一个月内超过一天的时间里得到重复的任何人。您也只能回顾 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 |