1

我有一个映射表如下:

FirstEntityID int
MappedTo int
BeginDate Date
EndDate Date

假设我在表中有以下记录:

FirstEntityID  MappedTo  BeginDate     EndDate 
     1             2     2012-09-01   2012-10-01
     2             3     2012-09-01   2012-10-01
     1             2     2012-10-02   2012-11-24
     2             3     2012-11-01   2012-11-24

我需要一个脚本来获取此表并根据开始和结束日期合并记录以返回如下结果:

   FirstEntityID  MappedTo  BeginDate     EndDate 
     1             2     2012-09-01   2012-11-24
     2             3     2012-09-01   2012-10-01
     2             3     2012-11-01   2012-11-24
4

3 回答 3

3

使用 CTE,我们首先找到开始日期:

; WITH StartD AS
  ( SELECT 
        FirstEntityID
      , MappedTo
      , BeginDate
      , ROW_NUMBER() OVER( PARTITION BY FirstEntityID, MappedTo
                           ORDER BY BeginDate )
          AS Rn 
    FROM
        tableX AS t
    WHERE
        NOT EXISTS
        ( SELECT *
          FROM tableX AS p
          WHERE p.FirstEntityID = t.FirstEntityID
            AND p.MappedTo = t.MappedTo
            AND p.BeginDate < t.BeginDate 
            AND t.BeginDate <= DATEADD(day, 1, p.EndDate)
        )
  )

然后是结束日期:

, EndD AS
  ( SELECT 
        FirstEntityID
      , MappedTo
      , EndDate
      , ROW_NUMBER() OVER( PARTITION BY FirstEntityID, MappedTo
                           ORDER BY EndDate )
          AS Rn 
    FROM
        tableX AS t
    WHERE
        NOT EXISTS
        ( SELECT *
          FROM tableX AS p
          WHERE p.FirstEntityID = t.FirstEntityID
            AND p.MappedTo = t.MappedTo
            AND DATEADD(day, -1, p.BeginDate) <= t.EndDate
            AND t.EndDate < p.EndDate
        )
  )

和最终结果:

SELECT
    s.FirstEntityID
  , s.MappedTo
  , s.BeginDate
  , e.EndDate
FROM
    StartD AS s
  JOIN
    EndD AS e
      ON  e.FirstEntityID = s.FirstEntityID
      AND e.MappedTo = s.MappedTo
      AND e.Rn = s.Rn ;

SQL-Fiddle中测试

于 2012-09-25T11:07:44.887 回答
1

测试了这个,它似乎工作

它将在具有重复行的边缘情况下失败。
为此,需要使用像 Ypercube 这样的 RowNumber 方法。
或者在表上添加一个约束来强制该行是唯一的。

-- first the overlaps
SELECT T1.FirstEntityId, T1.MappedTo, T1.BeginDate, Max(T2.EndDate) as [EndDate]
FROM tablex as T1
join tablex as T2  
  on  T1.FirstEntityId = T2.FirstEntityId
  and T1.MappedTo = T2.MappedTo
  and T1.EndDate >= T2.BeginDate 
  and T1.EndDate <  T2.EndDate
  and T1.BeginDate <= T2.BeginDate
GROUP BY T1.FirstEntityId, T1.MappedTo, T1.BeginDate  

union

-- add the non overlaps
SELECT T1.FirstEntityId, T1.MappedTo, T1.BeginDate, T1.EndDate
FROM tablex as T1
join tablex as T2  
  on  T1.FirstEntityId = T2.FirstEntityId
  and T1.MappedTo = T2.MappedTo
  and (  T1.EndDate  < T2.BeginDate or T1.BeginDate > T2.EndDate 
   or   (T1.BeginDate  < T2.BeginDate and T1.EndDate > T2.EndDate) )

order by FirstEntityId, MappedTo, BeginDate
于 2012-09-24T23:05:57.347 回答
0

这可能有效:

SELECT FirstEntityId, MappedTo, Min(BeginDate), Max(EndDate)
FROM
    T1
GROUP BY
    FirstEntityId, MappedTo
于 2012-09-24T22:52:55.263 回答