按日期排序时,请为每组代码编号(使用空值和重复代码)

时间:2018-06-14 23:37:12

标签: sql-server gaps-and-islands

我有一组数据如下 - 它由EmpID和EffDate订购。注意:这是一个EmpID的示例数据集,但会有多个EmpID。

我正在尝试编写SQL(对于SQL Server 2008)以返回Grp列中的值。例如,当按EffDate排序时,为每组PosCode编号,直到PosCode发生变化。我不介意Grp值是否不连续(1,2,3,4等),它可以是(2,5,7,8等),只要它们按唯一的Grp数分组。

EmpID   EffDate     PosCode EndDate     Grp
1360    2013-10-05  NULL    NULL        1
1360    2014-08-04  NULL    NULL        1
1360    2015-03-16  P504    2015-04-05  2
1360    2016-01-04  P504    2016-01-15  2
1360    2016-08-01  NULL    NULL        3
1360    2017-01-30  NULL    NULL        3
1360    2017-02-13  NULL    NULL        3
1360    2018-03-29  P503    2018-07-02  4
1360    2018-05-10  P503    2018-07-02  4
1360    2018-07-02  P503    2018-11-23  4
1360    2018-11-24  P504    2018-12-23  5

这是我能得到的最接近的,但是当我需要将它们分成两个不同的组时,所有的空值都被组合在一起

select 
    EmpID, EffDate, PosCode, EndDate
    ,row_number() over (order by EffDate) 
        - row_number() over (partition by PosCode order by EffDate) as grp
from #p
order by 1, 2


EmpID   EffDate     PosCode EndDate     Grp
1360    2013-10-05  NULL    NULL        0
1360    2014-08-04  NULL    NULL        0
1360    2015-03-16  P504    2015-04-05  2
1360    2016-01-04  P504    2016-01-15  2
1360    2016-08-01  NULL    NULL        2
1360    2017-01-30  NULL    NULL        2
1360    2017-02-13  NULL    NULL        2
1360    2018-03-29  P503    2018-07-02  7
1360    2018-05-10  P503    2018-07-02  7
1360    2018-07-02  P503    2018-11-23  7
1360    2018-11-24  P504    2018-12-23  8

我想我可能需要使用APPLY来确定PosCode何时发生变化。我尝试了一些东西,但我无法让它发挥作用。

谢谢!

ETA:使用Gordon的代码(我添加了ORDER BY 1,2),我仍然遇到第二组有5个成员的问题,当一个新组应该在NULL开始时启动

EmpID   EffDate     PosCode EndDate     seqnum_p    seqnum_ep   grp
1360    2013-10-05  NULL    NULL        1   1   1
1360    2014-08-04  NULL    NULL        2   2   1
1360    2015-03-16  P504    2015-04-05  3   1   2
1360    2016-01-04  P504    2016-01-15  4   2   2
1360    2016-08-01  NULL    NULL        5   3   2
1360    2017-01-30  NULL    NULL        6   4   2
1360    2017-02-13  NULL    NULL        7   5   2
1360    2018-03-29  P503    2018-07-02  8   1   3
1360    2018-05-10  P503    2018-07-02  9   2   3
1360    2018-07-02  P503    2018-11-23  10  3   3
1360    2018-11-24  P504    2018-12-23  11  3   4

1 个答案:

答案 0 :(得分:0)

这是“间隙和岛屿”问题的一个例子。在SQL Server 2008中,您可以使用不同的行号来处理它:

select t.*,
       dense_rank() over (partition by empid order by min_id) as grp
from (select t.*,
             min(id) over (partition by empid, poscode, seqnum_p - seqnum_ep) as min_id
      from (select t.*,
                   row_number() over (partition by empid order by effdate) as seqnum_p,
                   row_number() over (partition by empid, poscode order by effdate) as seqnum_ep
            from t
           ) t
     ) t;

解释这是如何工作有点棘手。我的建议是运行子查询并盯着行号函数的结果。您将看到您想要识别的组的差异如何不变。