这个答案有一些假设。
假设
数据集一次只针对一名员工。如果不是,
还有另外一列,比如EmployeeID,那么你会
想在over 内的partition by 子句中指定它
我的 cmets 表示的子句。
-
EmployeeStatusCatalog 值具有以下含义:
“雇用”或“重新雇用”交易被视为发生
在初始 A 状态或 I 状态结束后。
示例数据设置
不包括 EmployeeStatusId 列,因为我的假设是它与创建预期结果无关。
declare @employee table
(
EffectiveStartDate date not null
, EffectiveEndDate date not null
, EmployeeStatusCatalog char(1) not null
)
insert into @employee
values ('2008-02-29', '2016-05-31', 'A')
, ('2016-06-01', '2016-06-30', 'A')
, ('2016-07-01', '2016-07-30', 'L')
, ('2016-07-31', '2016-09-02', 'A')
, ('2016-09-03', '2016-10-09', 'I')
, ('2016-10-10', '2016-11-01', 'A')
, ('2016-11-02', '2016-12-02', 'L')
, ('2016-12-03', '2016-12-05', 'I')
, ('2016-12-06', '2016-12-06', 'A')
, ('2016-12-07', '2017-01-01', 'L')
, ('2017-01-02', '9999-12-31', 'A')
回答
您可能知道也可能不知道,这是一个经典的gaps and islands 场景。在 Hire/Rehire 日期之间的每个段都是一个岛(在此示例中没有间隙)。
我使用CTE 将I 状态前移一行(通过LAG 函数),然后获取I 行数的运行计数,为每个岛分配一个“ID”号.
之后,使用min 函数,同时按岛号划分,确定每个岛的最小EffectiveStartDate。
; with inactive_dts as
(
--move the I status forward one row
select e.EffectiveStartDate
, e.EffectiveEndDate
, e.EmployeeStatusCatalog
, lag(e.EmployeeStatusCatalog, 1, 'A') over (/*partion by here*/ order by e.EffectiveStartDate asc) as prev_status
from @employee as e
where 1=1
)
, active_island_nbr as
(
--get the running count of the number of I rows
select a.EffectiveStartDate
, a.EffectiveEndDate
, a.EmployeeStatusCatalog
, a.prev_status
, sum(case a.prev_status when 'I' then 1 else 0 end) over (/*partition by here*/ order by a.EffectiveStartDate asc) as ActiveIslandNbr
from inactive_dts as a
)
select min(a.EffectiveStartDate) over (partition by a.ActiveIslandNbr) as HireRehireDate
, a.EffectiveStartDate
, a.EffectiveEndDate
, a.EmployeeStatusCatalog
from active_island_nbr as a
结果
HireRehireDate EffectiveStartDate EffectiveEndDate EmployeeStatusCatalog
2008-02-29 2008-02-29 2016-05-31 A
2008-02-29 2016-06-01 2016-06-30 A
2008-02-29 2016-07-01 2016-07-30 L
2008-02-29 2016-07-31 2016-09-02 A
2008-02-29 2016-09-03 2016-10-09 I
2016-10-10 2016-10-10 2016-11-01 A
2016-10-10 2016-11-02 2016-12-02 L
2016-10-10 2016-12-03 2016-12-05 I
2016-12-06 2016-12-06 2016-12-06 A
2016-12-06 2016-12-07 2017-01-01 L
2016-12-06 2017-01-02 9999-12-31 A