对表格问题进行分组

时间:2016-11-02 08:37:46

标签: sql-server sql-server-2012 group-by

我的表格包含四个字段:IDDateBegDateEndRankIDRankID值是ID字段超过DateBeg asc的等级。这是样本数据:

ID |RankID |  DateBeg    |  DateEnd  |
---|-------|--------------------------
1  | 1     |01-01-2016   |04-01-2016 |
1  | 2     |05-01-2016   |11-02-2016 |
1  | 3     |12-02-2016   |15-02-2016 |
1  | 4     |16-02-2016   |19-02-2016 |
1  | 5     |23-02-2016   |25-02-2016 |
4  | 2     |05-01-2016   |07-01-2016 |
4  | 3     |08-01-2016   |12-01-2016 |
5  | 1     |04-01-2016   |06-01-2016 |

现在,我想对ID记录进行分组,这些记录在前一个等级记录DateBeg值后1天具有DateEnd值(如果它为空,则必须也包含它)。 此示例表的所需结果将是:

ID | Min(DateBeg)|Max(DateEnd)|
---|-------------|----------------
1  |01-01-2016   |19-02-2016  |
1  |23-02-2016   |25-02-2016  |
4  |05-01-2016   |12-01-2016  |
5  |04-01-2016   |06-01-2016  |

希望你能帮助我,提前谢谢。

2 个答案:

答案 0 :(得分:3)

尝试如下。我假设您的datebegDateend是日期数据类型格式。否则,您需要转换为日期数据类型进行比较。

SELECT ID,MIN(DATEBEG),MAX(DateEnd) FROM
    (
    SELECT ID,(DATEBEG),ROW_NUMBER()OVER(PARTITION BY ID ORDER BY ID) RNO,

    (DateEND),CASE WHEN DATEBEG=LAG( DATEADD(DAY,1,[DateEnd])) 
    OVER(PARTITION BY ID ORDER BY ID)THEN  1 END  NO
    FROM #TABLE1
    )A
    GROUP BY ID,ISNULL(NO,RNO)
    ORDER BY ID

更新: - 试试以下。如果您的数据集中有唯一的ud和rank id组合,它将适用于所有场景,否则使用row_number并生成唯一的数字。

SELECT ID,MIN(DATEBEG),MAX(DATEEND) FROM 
(
SELECT ID,
       RANKID,
       datebeg, 
      DateEnd,
       CASE
         WHEN Dateadd(DAY, -1,  datebeg) = Lag( DateEnd) OVER(PARTITION BY ID ORDER BY ID)                                                        
       OR   Dateadd(DAY, 1, dateEND) = LEAD( DateBeg) OVER(PARTITION BY ID ORDER BY ID)                                                       
      THEN 1
         ELSE 0
       END NO
FROM   #Table1 
)A
GROUP BY ID,CASE WHEN NO=0 AND ID<>RANKID THEN RANKID ELSE NO END
ORDER BY ID

答案 1 :(得分:2)

以下是算法:

  1. 检测间隙。给每个不遵循先前记录的记录立即给出差距#1。因此,每个开始新组的记录都会被标记为#1。
  2. 建立差距编号的运行总计。因此,组中的所有记录都会得到相同的数字。
  3. 按群组分组,并显示每组的最低开始日期和最长结束日期。
  4. SQL Server查询:

    select id, min(datebeg), max(dateend)
    from
    (
      select
        id,
        datebeg,
        dateend,
        sum(gap) over (partition by id order by datebeg) as grp
      from
      (
        select 
          id,
          datebeg,
          dateend,
          case when datebeg <> 
                    dateadd(day, 1, lag(dateend) over (partition by id order by datebeg)) 
               then 1 else 0 end as gap
        from mytable
      ) with_gap_flags
    ) with_group_numbers
    group by id, grp
    order by id, grp;
    

    SQL小提琴:http://sqlfiddle.com/#!6/f473ae/1