SQL to determine multiple date ranges (SQL Server 2000)

后端 未结 5 1102
小蘑菇
小蘑菇 2021-01-15 01:20

I have a table which contains an ID and a Date for an event. Each row is for one date. I am trying to determine consecutive date ranges and consoli

5条回答
  •  逝去的感伤
    2021-01-15 01:48

    I've just done this similar thing in SQL Server 2008. I think the following translation will work for SQL Server 2000:

    -- Create table variable
    DECLARE @StartTable TABLE
    (
      rowid INT IDENTITY(1,1) NOT NULL,
      userid int,
      startDate date
    )
    
    Insert Into @StartTable(userid, startDate)
    --This finds the start dates by finding unmatched values
    SELECT t1.ID, t1.[Date]
    FROM Example As t1
    LEFT OUTER JOIN Example As t2 ON t1.ID=t2.ID 
       And DateAdd(day, 1, t2.[Date]) = t1.[Date]
    WHERE t2.[Date] Is NULL
    ORDER BY t1.ID, t1.[Date]
    
    -- Create table variable
    DECLARE @EndTable TABLE
    (
      rowid INT IDENTITY(1,1) NOT NULL,
      userid int,
      endDate date
    )
    
    Insert Into @EndTable(userid, endDate)
    --This finds the end dates by getting unmatched values 
    SELECT t1.ID, t1.[Date]
    FROM Example As t1
    LEFT OUTER JOIN Example As t2 ON t1.ID=t2.ID
       And DateAdd(day, -1, t2.[Date]) = t1.[Date]
    WHERE t2.[Date] IS NULL
    ORDER BY t1.ID, t1.[Date]
    
    Select eT.userid, startDate, endDate 
    From @EndTable eT
    INNER JOIN @StartTable sT On eT.userid = sT.userid 
    AND eT.rowid = sT.rowid;
    

    So as you can see, I created two table variables, one for starts and one for ends, by self-joining the table on the date either just prior to or just after the date in the [Date] column. This means that I'm selecting only records that don't have a date prior (so these would be at the beginning of a period) for the Start Table and those that have no date following (so these would be at the end of a period) for the End Table.

    When these are inserted into the table variable, they are numbered in sequence because of the Identity column. Then I join the two table variables together. Because they are ordered, the start and end dates should always match up properly.

    This solution works for me because I have at most one record per ID per day and I am only interested in days, not hours, etc. Even though it is several steps, I like it because it is conceptually simple and eliminates matched records without having cursors or loops. I hope it will work for you too.

自定义标题
段落格式
字体
字号
代码语言
提交回复
热议问题