【问题标题】:update a column with the latest hiredate of an employee使用员工的最新雇用日期更新列
【发布时间】:2018-01-26 09:01:23
【问题描述】:

我有一个员工状态历史记录表。

我需要再创建一个列来复制每一行的 min(EffectiveStartDate),直到重新雇用员工。我需要获取 UI 将通过日期的员工的服务年限。

如何在 SQL server 2014 中实现

【问题讨论】:

  • 只是想回头看看我给出的答案是否足够清楚,或者您是否还有其他问题。如果答案是您要寻找的答案,请继续并接受答案(在答案旁边打勾),让其他人后来偶然发现这个问题,这实际上就是解决方案。

标签: tsql sql-server-2014 gaps-and-islands


【解决方案1】:

这个答案有一些假设。

假设

  1. 数据集一次只针对一名员工。如果不是, 还有另外一列,比如EmployeeID,那么你会 想在over 内的partition by 子句中指定它 我的 cmets 表示的子句。

  2. EmployeeStatusCatalog 值具有以下含义:

    • 答:活跃
    • L:请假(缺席)
    • 我:不活动
  3. “雇用”或“重新雇用”交易被视为发生 在初始 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 日期之间的每个段都是一个岛(在此示例中没有间隙)。

我使用CTEI 状态前移一行(通过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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-05
    • 1970-01-01
    • 1970-01-01
    • 2017-06-24
    • 2023-03-26
    • 1970-01-01
    相关资源
    最近更新 更多