在SQL中使用RANK作为记录组的ID号

问题描述

这是我的桌子:

employeeid  workdate                workstatus
----------- ----------------------- ----------
1           2020-09-01 00:00:00.000 ON 
1           2020-09-02 00:00:00.000 ON 
1           2020-09-03 00:00:00.000 ON 
1           2020-09-04 00:00:00.000 OFF
1           2020-09-05 00:00:00.000 OFF
2           2020-09-01 00:00:00.000 ON 
2           2020-09-02 00:00:00.000 ON 
2           2020-09-03 00:00:00.000 OFF
2           2020-09-04 00:00:00.000 OFF
2           2020-09-05 00:00:00.000 ON 

我正在执行此查询

select employeeid,workdate,workstatus,rank() over(partition by employeeid,workstatus order by workdate) as cycle
from #workstatus
order by 1,2

结果如下:

employeeid  workdate                workstatus cycle
----------- ----------------------- ---------- --------------------
1           2020-09-01 00:00:00.000 ON         1
1           2020-09-02 00:00:00.000 ON         2
1           2020-09-03 00:00:00.000 ON         3
1           2020-09-04 00:00:00.000 OFF        1
1           2020-09-05 00:00:00.000 OFF        2
2           2020-09-01 00:00:00.000 ON         1
2           2020-09-02 00:00:00.000 ON         2
2           2020-09-03 00:00:00.000 OFF        1
2           2020-09-04 00:00:00.000 OFF        2
2           2020-09-05 00:00:00.000 ON         3

我的目标是通过每个员工的唯一编号来标识开/关工作的“周期”。因此,员工1的三个工作日为周期1,那么两个工作日为周期2。

员工2的前两个工作日为第1个周期,然后这两个工作日为第2个周期,最后一个工作日为第3个周期。

我不确定是否可以为此使用RANK()或是否有更好的解决方案。谢谢!

解决方法

这是一种空白和岛屿问题。对于此版本,请使用lag()和累计金额:

select t.*,sum(case when prev_ws= workstatus then 0 else 1 end) over 
           (partition by employeeid order by workdate) as ranking
from (select t.*,lag(workstatus) over (partition by employeeid order by workdate) as prev_ws
      from t
     ) t;
,

使用density_rank代替等级

,

您可以使用窗口功能来解决此“空缺”问题。一种方法是利用行号之间的差异来构建“相邻”记录组:

select employeeid,workdate,workstatus,row_number() over(partition by employeeid,rn1 - rn2 order by workdate) cycle
from (
    select t.*,row_number() over(partition by employeeid order by workdate) rn1,workstatus order by workdate) rn2
    from mytable t
) t