根据日期返回一组连续记录的最小开始日期,最大结束日期和最新类别

时间:2019-07-04 12:30:41

标签: sql sql-server

我有一个表,其中包含人员ID,Category_ID,开始日期,结束日期和类别。当“开始日期”与“上一个结束日期”相同时,这是一个延续,仅表示类别更改。在一个连续的日期范围内,可能会有许多类别更改。

我想返回每个人的“开始日期”,“结束日期”和“类别类型”。

我考虑过确定所有具有连续日期范围的人,并返回最大值和最小值等。但是,当一个人具有多个连续日期范围(即一个期间结束并且有休息)时,这没有考虑在内然后还有另一个连续的时期,类别发生了变化。

示例输出:

+---------+------------+------------+---------------+
|   ID    |  start_dt  |   end_dt   | category_type |
+---------+------------+------------+---------------+
| 8105755 | 26/01/2016 | 21/04/2016 | D             |
| 8105859 | 21/04/2016 | 22/04/2016 | A             |
| 8105861 | 22/04/2016 | 26/04/2016 | D             |
| 8105870 | 26/04/2016 | 19/10/2016 | A             |
+---------+------------+------------+---------------+

因此,在这种情况下,因为end_dt与每行的前一个start_dt相同,所以这是一个连续的时间段,因此我想返回具有“第一开始日期”,“最后结束日期”和“最新类别类型”的一行,如下所示:< / p>

+---------+------------+------------+---------------+
|   ID    |  start_dt  |   end_dt   | category_type |
+---------+------------+------------+---------------+
| 8105870 | 26/01/2016 | 19/10/2016 | A             |
+---------+------------+------------+---------------+

1 个答案:

答案 0 :(得分:0)

这是一种“空白与孤岛”问题,您可以使用累积总和来识别组来解决。总和基于组开始的时间。所以:

select distinct
       first_value(t.id) over (partition by grp order by t.start_dt desc) as id,
       min(t.start_dt) over (partition by grp) as start_dt,
       max(t.start_dt) over (partition by grp) as end_dt,
       first_value(t.category) over (partition by grp order by t.start_dt desc) as id
from (select t.*,
             sum(case when t.id is null then 1 else 0 end) over (order by t.start_dt) as grp
      from t left join
           t tprev
           on tprev.end_dt = t.start_dt
     ) t;

注意:之所以使用select distinct是因为SQL Server不提供用于聚合的“ first()” /“ last()”函数。