我有一组数据如下 - 它由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
答案 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;
解释这是如何工作有点棘手。我的建议是运行子查询并盯着行号函数的结果。您将看到您想要识别的组的差异如何不变。