【问题标题】:I need a way to group data based on previous rows我需要一种基于先前行对数据进行分组的方法
【发布时间】:2017-11-29 12:25:24
【问题描述】:

让我再解释一下。

此表记录了每个人每月每一天的记录。表中有大约 20 个字段。如果任何字段发生变化(日期字段除外),那么我想对这些记录进行分组。因此,例如,如果第 1、2 和 3 天相同,那么当我在第 4 天阅读并注意到它发生了变化时,我想将第 1、2 和 3 天与第 1 天的开始日期组合在一起,以及第 3 天的结束日期...等

Rownum  ID BegDate  EndDate   Field1, Field2.... Field20
 1      1  6/1/2017 6/1/2017  xxxx    xxxx        xxxxx
 2      1  6/2/2017 6/2/2017  xxxx    xxxx        xxxxx
 3      1  6/3/2017 6/3/2017  xxxx    xxxx        xxxxx
 4      1  6/4/2017 6/4/2017  yyyy    yyyy        yyyy
 5      1  6/5/2017 6/5/2017  yyyy    yyyy        yyyy
 6      1  6/6/2017 6/6/2017  xxxx    xxxx        xxxxx
 7      1  6/7/2017 6/7/2017  xxxx    xxxx        xxxxx
 8      1  6/8/2017 6/8/2017  zzzz    zzzz        zzzz
....

所以在上面的示例数据中,我将有一个第 1,2,3 行的组,然后是第 4,5 行的组,然后是第 6,7 行的组,然后是第 8 行的组......等等

ID  BegDate    EndDate  Field1  Field2 ...... Field20   Sum
1   6/1/2017   6/3/2017  xxxx    xxxx          xxxxx      3
1   6/4/2017   6/5/2017  yyyy    yyyy          yyyy       2
1   6/6/2017   6/7/2017  xxxx    xxxx          xxxxx      2
1   6/8/2017   6/15/2017 zzzz    zzzz          zzzz       8
.....

【问题讨论】:

  • 编辑您的问题并提供示例数据。
  • 样本数据集在这里会有所帮助 - 但研究 LAG
  • 正如@GordonLinoff 所说,请提供样本数据和所需的结果数据集。解决方案可能是一个窗口函数。

标签: sql sql-server gaps-and-islands


【解决方案1】:

例如。创建表:

 create table t
 (date_ datetime,
  status varchar(1));

并添加数据

  insert into t values ('2017-11-01','A');
  insert into t values ('2017-11-02','A');
  insert into t values ('2017-11-03','A');
  insert into t values ('2017-11-04','B');
  insert into t values ('2017-11-05','B');
  insert into t values ('2017-11-06','B');
  insert into t values ('2017-11-07','C');
  insert into t values ('2017-11-08','C');
  insert into t values ('2017-11-09','C');
  insert into t values ('2017-11-10','C');
  insert into t values ('2017-11-11','B');
  insert into t values ('2017-11-12','B');
  insert into t values ('2017-11-13','B');
  insert into t values ('2017-11-14','B');
  insert into t values ('2017-11-15','B');

并使用此查询

 select min(date_start),
           IFNULL(date_end,now()),
           status
    from 
    ( select 
      t1.date_ date_start,
      (select min(date_) from t t2 where t2.date_>t1.date_ and t2.status<>t1.status) - interval 1 day as 'date_end',
     t1.status status
    from t t1
      ) a
      group by date_end,status
      order by 1

http://sqlfiddle.com/#!9/96e27/11

【讨论】:

    【解决方案2】:

    您可以通过不同的行号来做到这一点:

    select ID, min(BegDate) as Begdate, max(EndDate) as max(EndDate),
           Field1, Field2, ...... Field20,
           datediff(day, min(BegDate), max(EndDate))
    from (select t.*,
                 row_number() over (partition by id order by begdate) as seqnum,
                 row_number() over (partition by id, Field1, Field2, . . ., Field20 order by begdate) as seqnum_2
          from t
         ) t
    group by id, (seqnum - seqnum_2), Field1, Field2, . . . Field20 ;
    

    【讨论】:

      【解决方案3】:

      尝试以下查询(带有 2 个额外字段 - field1 和 field2)。 要处理 20 个字段,请在您看到 field1、field2 和 field1、field2、field3、......field20 的任何地方添加剩余列

          create table #tmp (RowNum int, id int,begdate datetime,EndDate datetime, field1 varchar(10),field2 varchar(10))
      
          insert into #tmp values(1,1,'2017-06-01','2017-06-01','xxxxx','xxxxx')
          insert into #tmp values(2,1,'2017-06-02','2017-06-02','xxxxx','xxxxx')
          insert into #tmp values(3,1,'2017-06-03','2017-06-03','xxxxx','xxxxx')
          insert into #tmp values(4,1,'2017-06-04','2017-06-04','yyyyy','yyyyy')
          insert into #tmp values(5,1,'2017-06-05','2017-06-05','yyyyy','yyyyy')
          insert into #tmp values(6,1,'2017-06-06','2017-06-06','xxxxx','xxxxx')
          insert into #tmp values(7,1,'2017-06-07','2017-06-07','xxxxx','xxxxx')
          insert into #tmp values(8,1,'2017-06-08','2017-06-08','zzzzz','zzzzz')
          insert into #tmp values(9,1,'2017-06-09','2017-06-09','zzzzz','zzzzz')
          insert into #tmp values(10,1,'2017-06-10','2017-06-10','zzzzz','zzzzz')
      
          insert into #tmp values(11,2,'2017-06-04','2017-06-04','yyyyy','yyyyy')
          insert into #tmp values(12,2,'2017-06-05','2017-06-05','yyyyy','yyyyy')
          insert into #tmp values(13,2,'2017-06-06','2017-06-06','xxxxx','xxxxx')
          insert into #tmp values(14,2,'2017-06-07','2017-06-07','xxxxx','xxxxx')
      
      
          insert into #tmp values(15,1,'2017-06-11','2017-06-11','xxxxx','xxxxx')
          insert into #tmp values(16,1,'2017-06-12','2017-06-12','xxxxx','xxxxx')
          insert into #tmp values(17,1,'2017-06-13','2017-06-13','zzzzz','xxxxx')
          insert into #tmp values(18,1,'2017-06-14','2017-06-14','zzzzz','xxxxx')
          insert into #tmp values(19,1,'2017-06-15','2017-06-15','yyyyy','xxxxx')
          insert into #tmp values(20,1,'2017-06-16','2017-06-16','zzzzz','xxxxx')
      
      
          select ID, min(BegDate) as Begdate, max(EndDate) as EndDate,
                 Field1,Field2, /*Add all other fields here*/
                 datediff(day, min(BegDate), max(EndDate))+1 As [Sum]
          from(
          select *,
                       row_number() over (partition by id order by begdate) as seqnum,
                       row_number() over (partition by id, Field1,field2 /*Add all other fields here*/ order by begdate) as seqnum_2
                from #tmp
      
              ) t
          group by id, (seqnum - seqnum_2), Field1,Field2 /*Add all other fields here*/
          order by ID,Begdate
      
      
          Drop table #tmp
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-10
        • 2015-11-14
        • 2019-05-15
        • 1970-01-01
        • 2022-06-12
        • 1970-01-01
        • 2014-04-09
        • 2013-08-16
        相关资源
        最近更新 更多