根据两个单独的排名/分组将日期时间分组在一起

时间:2019-01-30 12:36:19

标签: sql sql-server sql-server-2012

您好,我对我措辞不好的标题感到抱歉,我不确定如何准确表达我的需要。但我会在下面尝试更好地解释它:

我有一个看起来像这样的数据集:

DECLARE @TestDATA TABLE (PERSON_ID int, START_DATE date, END_DATE date,SERVICE_RANK int)

INSERT INTO @TestDATA 
VALUES 
(123, '2018-01-31', '2018-02-14', 7), 
(123, '2018-03-28', '2018-04-11', 4), 
(123, '2018-04-12', '2018-04-30', 4), 
(123, '2018-05-25', '2018-06-08', 7), 
(123, '2018-06-08', '2018-06-15', 7), 
(123, '2018-06-19', '2018-06-26', 7), 
(123, '2018-06-26', '2018-09-28', 4), 
(123, '2018-10-10', '2018-11-07', 7), 
(123, '2018-11-27', '2018-12-11', 7), 
(123, '2018-12-11', '2018-12-24', 7)

其中显示了每个人的日期范围和“服务等级”(此示例中只有一个人,但是数据库中有成千上万的人)

我想在每个person_id和每个service_rank的位置对日期段进行分组,以识别它们具有多少个不同的时期。因此,在上面的示例中,这就是我想要的:

PERSON ID, START_DATE,  END_DATE,  SERVICE_RANK, SERVICE_PERIOD    
    123    2018-01-31   2018-02-14     7             1
    123    2018-03-28   2018-04-11     4             2
    123    2018-04-12   2018-04-30     4             2
    123    2018-05-25   2018-06-08     7             3
    123    2018-06-08   2018-06-15     7             3
    123    2018-06-19   2018-06-26     7             3
    123    2018-06-26   2018-09-28     4             4
    123    2018-10-10   2018-11-07     7             5
    123    2018-11-27   2018-12-11     7             5
    123    2018-12-11   2018-12-24     7             5  

我尝试了row_number,rank,densage_rank甚至尝试了可怕的CURSOR FOR,但是由于窗口函数将服务等级视为相同,所以我无法完成任何工作,因此对于上面的示例,它将看到两个服务等级当实际上有5个时,它们只是共享相同的编号。

在数据集中,并不是每个人都会从一个service_rank跳到另一个,然后返回。他们可能会从一个地方移到另一个地方(例如4-> 7)并留在那里,或者他们在多个行上可能只有一个service_rank。

任何想法?

1 个答案:

答案 0 :(得分:2)

这是一个孤岛问题。为此,一种方法是lag()和累计和:

select t.*,
       sum(case when prev_service_rank = service_rank then 0 else 1 end) over (partition by person_id order by start_date) as service_period
from (select t.*,
             lag(service_rank) over (partition by person_id order by start_date) as prev_service_rank
      from t
     ) t;