2012-09-24 26 views
1

之間我有一個映射表如下無間隙:TSQL最好的方式合併開始日期和結束日期記錄時存在

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 
+1

無法看到如何從4行到3行的邏輯。 – Paparazzi

+0

@Blam與firstEntityID = 1和mappedTo = 2的記錄已重複但從第一個記錄結束日期繼續沒有差距 – Asha

+0

而我們應該從「基於開始和結束日期的合併記錄」得到這個?如果有第三個1 2沒有重疊呢? – Paparazzi

回答

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

+0

嗨,謝謝。只是一個澄清:正如你可以看到在我的例子1至2的結束日期已更新,但它不能像你的代碼那樣工作。有沒有可能修改它? – Asha

+0

是的,有一個錯字。檢查更新和新鏈接 –

+0

+1在重複的行上,它似乎報告了我的測試。 – Paparazzi

0

這可能會實現:

SELECT FirstEntityId, MappedTo, Min(BeginDate), Max(EndDate) 
FROM 
    T1 
GROUP BY 
    FirstEntityId, MappedTo 
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 
相關問題