使用最新的员工雇员更新列

时间:2017-08-17 19:40:31

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

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

EmployeeSTatusHistory

我需要再创建一个列,该列应该复制每行的min(EffectiveStartDate),直到重新雇用员工。我需要获得员工的服务期限,其中日期将由UI传递。

NewCOlumn HireRehireDate

我如何在SQL Server 2014中实现

1 个答案:

答案 0 :(得分:0)

这个答案有一些假设。

<强>假设

  1. 数据集一次仅适用于一名员工。如果不是, 还有另一列,例如EmployeeID,那么你会 想要在partition by内的over子句中指定 条款,我的评论表示。

  2. EmployeeStatusCatalog值具有以下含义:

    • A:有效
    • L:离开(缺席)
    • 我:无效
  3. 认为发生“雇用”或“重新雇佣”交易 在初始A状态或I状态结束后。

  4. 示例数据设置

    未包含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场景。雇佣/重新雇佣日期之间的每个部分都是岛屿(本例中没有间隙)。

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