如何找到具有连续时间列的行组合

时间:2015-05-18 13:32:14

标签: sql sql-server

这个问题对我来说有点头疼。我正在为医疗保健访问者建立一个BI项目,但遗憾的是他们的数据注册非常糟糕。在图中所示的示例中,我有以下列:

  1. 特定人员的身份证号码
  2. 食物类型
  3. 该特定食品类型的开始日期
  4. 结束日期
  5. 对于A人,医疗保健访客已连续3次注册相同的食物类型,即使它只应注册为一个长期。我想组合这3行,这样我只有一行包含ID,食物类型,FIRST开始日期和最后结束日期(斜体)如果当前列的结束日期与新开始日期相同每种特定食物类型的下一栏。这同样适用于人员B,其中3行应合并为1行,包含开始日期和结束日期(斜体)

    • ID FoodType StartDate EndDate
    • [PersonA] ... S002 ... 04-11-2014 ... 10-11-2014
    • [PersonA] ... S002 ... 10-11-2014 ... 08-01-2015
    • [PersonA] ... S002 ... 08-01-2015 ... 24-03-2015
    • [PersonA] ... S006 ... 24-03-2015 ... 1753-01-01
    • [PersonB] ... S002 ... 06-08-2013 ... 16-08-2013
    • [PersonB] ... S002 ... 16-08-2013 ... 26-08-2013
    • [PersonB] ... S002 ... 26-08-2013 ... 12-12-2013
    • [PersonB] ... S008 ... 12-12-2013 ... 11-02-2014

    所以我会得到这张表:

    • ID食物类型StartDate EndDate
    • [PersonA] ... S002 ... 04-11-2014 ... 24-03-2015
    • [PersonA] ... S006 ... 24-03-2015 ... 1753-01-01
    • [PersonB] ... S002 ... 06-08-2013 ... 12-12-2013
    • [PersonB] ... S008 ... 12-12-2013 ... 11-02-2014

    以下是创建表的SQL查询。

    CREATE TABLE [dbo].[CombineDates](
    [ID] [varchar](36) NULL,
    [FoodType] [varchar](10) NULL,
    [StartDate] [datetime] NULL,
    [EndDate] [datetime] NULL) ON [PRIMARY]
    
    insert into CombineDates([ID],[FoodType],[StartDate],[EndDate])
    values('Person A','S002','2014-11-04 00:00:00.000','2014-11-10 00:00:00.000')
    insert into CombineDates([ID],[FoodType],[StartDate],[EndDate])
    values('Person A','S002','2014-11-04 00:00:00.000','2014-11-10 00:00:00.000')
    insert into CombineDates([ID],[FoodType],[StartDate],[EndDate]) 
    values('Person A','S002','2014-11-10 00:00:00.000','2015-01-08 00:00:00.000')
    insert into CombineDates([ID],[FoodType],[StartDate],[EndDate]) 
    values('Person A','S002','2015-01-08 00:00:00.000','2015-03-24 00:00:00.000')
    insert into CombineDates([ID],[FoodType],[StartDate],[EndDate]) 
    values('Person B','S002','2013-08-06 00:00:00.000','2013-08-16 00:00:00.000')
    insert into CombineDates([ID],[FoodType],[StartDate],[EndDate]) 
    values('Person B','S002','2013-08-16 00:00:00.000','2013-08-26 00:00:00.000')
    insert into CombineDates([ID],[FoodType],[StartDate],[EndDate]) 
    values('Person B','S002','2013-08-26 00:00:00.000','2013-12-12 00:00:00.000')
    insert into CombineDates([ID],[FoodType],[StartDate],[EndDate]) 
    values('Person B','S008','2013-12-12 00:00:00.000','2014-02-11 00:00:00.000')
    
    select * from CombineDates
    
    希望你能帮助我。谢谢你和

    BR,

    的Jesper

1 个答案:

答案 0 :(得分:0)

接近这一点是为了确定一个人每次开始新的食物类型。您可以通过识别记录与之前的任何记录重叠来实现此目的。然后,通过计算"开始"的数量来识别连续值的组。在它之前的记录。

这使用累计金额。在SQL Server 2012+中,您可以这样做:

with cdf as (
      select cd.*
             (case when exists (select 1
                                from combinedates cd2
                                where cd2.id = cd.id and cd2.foodtype = cd.foodtype and
                                      cd2.startdate < cd.startdate and
                                      cd2.enddate >= cd.startdate
                               )
                   then 1 else 0
              end) as StartFlag
      from combinedates cd
     )
select id, foodtype, min(startdate) as startdate, max(enddate) as enddate
from (select cdf.*,
             sum(StartFlag) over (partition by id, foodtype order by startdate) as grp
      from cdf
     ) cdf
group by id, foodtype, grp

关于命名的说明。名为id的列应该是定义它的表中的唯一/主键列。这只是任何人阅读代码的期望,就像名为StartDate的列不是整数一样。 (我不会有这样的专栏,因为我的风格是主键包含表名。)

在您的表格中,此列应称为PersonId。我会更像这样定义表:

CREATE TABLE PersonFoods (
    PersonFoodId int identity(1, 1) not null primary key,
    PersonId varchar(36),
    FoodType varchar(10),
    StartDate datetime,
    EndDate datetime
);

鉴于您没有使用时间组件,datetime值可能只是date