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

When ordered by date, number each group of codes (with nulls and repeat codes)

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

我正在尝试将 SQL(对于 SQL Server 2008)写入 return 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

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

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

这是一个 "gaps-and-islands" 问题的例子。在 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;

解释它是如何工作的有点棘手。我的建议是 运行 子查询并查看行号函数的结果。您将看到对于您要识别的组而言,差异是如何保持不变的。