我有一份员工状态历史记录表。
我需要再创建一个列,该列应该复制每行的min(EffectiveStartDate),直到重新雇用员工。我需要获得员工的服务期限,其中日期将由UI传递。
我如何在SQL Server 2014中实现
答案 0 :(得分:0)
这个答案有一些假设。
<强>假设强>
数据集一次仅适用于一名员工。如果不是,
还有另一列,例如EmployeeID
,那么你会
想要在partition by
内的over
子句中指定
条款,我的评论表示。
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场景。雇佣/重新雇佣日期之间的每个部分都是岛屿(本例中没有间隙)。
我使用CTE将I
状态向前移动一行(通过LAG函数),然后获取I
行数的运行计数给每个岛屿一个“身份证”号码。
之后,使用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