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フィドルでテスト済み

于 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 に答える