以下は、範囲のリストを開始日と終了日のリストに「分解」するという点で、@Gordon Linoff の提案に似ています。ただし、結果のリストでは別の手法を使用します。また、開始日のみが含まれ、終了日は含まれないと想定しています。
WITH unpivoted AS (
SELECT
PropertyId,
EventDate,
OwnershipPercent,
PercentFactor = CASE EventDateType WHEN 'EndDate' THEN -1 ELSE 1 END
FROM Ownership
UNPIVOT (
EventDate FOR EventDateType IN (StartDate, EndDate)
) u
)
, summedup AS (
SELECT DISTINCT
PropertyId,
EventDate,
TotalPercent = SUM(OwnershipPercent * PercentFactor)
OVER (PARTITION BY PropertyId ORDER BY EventDate)
FROM unpivoted
)
SELECT
s.EventDate,
s.TotalPercent,
o.PropertyId,
o.PersonId,
o.StartDate,
o.EndDate,
o.OwnershipPercent
FROM summedup s
INNER JOIN Ownership o
ON s.PropertyId = o.PropertyId
AND s.EventDate >= o.StartDate
AND s.EventDate < o.EndDate
WHERE TotalPercent > 100 -- changed from the original "<= 100"
-- based on the verbal description
;
これがどのように機能するかを説明するために、の内容をOwnership
次のように仮定します。
PropertyId PersonId StartDate EndDate OwnershipPercent
---------- -------- ---------- ---------- ----------------
1 1 2010-01-01 2012-01-01 80
1 2 2011-01-01 2011-03-01 20
1 3 2011-02-01 2011-04-01 10
1 4 2011-05-01 2011-07-01 40
ここで、ピボットを解除する最初のステップで、元のテーブルのすべての行が 2 つの行に置き換えられるだけでなく、すべてのパーセント値が増分 ( PercentFactor = 1
) または減分 ( PercentFactor = -1
)としてマークされていることがわかります。開始日または終了日とともに表示されます。したがって、unpivoted
CTE は次の結果セットに評価されます。
PropertyId EventDate OwnershipPercent PercentFactor
---------- ---------- ---------------- -------------
1 2010-01-01 80 1
1 2011-01-01 20 1
1 2011-02-01 10 1
1 2011-03-01 20 -1
1 2011-04-01 10 -1
1 2011-05-01 40 1
1 2011-07-01 40 -1
1 2012-01-01 80 -1
この時点で、基本的には、値が増加するか減少するかを考慮して、OwnershipPercent
at every EventDate
for everyの実行中の合計を計算します。(実際には、 の別の列を割り当てる代わりに、最初の段階でPropertyId
符号を に組み込むことができます。アイデアをよりよく説明するために後者を選択しましたが、前者を好む場合、パフォーマンスのペナルティはないはずです。)は、実行中の合計を計算した後に得られるものです (これは、2 番目の CTE が行うことです)。OwnershipPercent
PercentFactor
summedup
PropertyId EventDate TotalPercent
---------- ---------- ------------
1 2010-01-01 80
1 2011-01-01 100
1 2011-02-01 110
1 2011-03-01 90
1 2011-04-01 80
1 2011-05-01 120
1 2011-07-01 80
1 2012-01-01 0
ただし、この結果のセットには重複する行が含まれる場合があることに注意してください。特に、同じPropertyId
に対して、一部の範囲が同時に開始または終了する場合、または一部の範囲が別の範囲の開始日に正確に終了する場合は、この問題が発生します。そのため、この段階で DISTINCT が使用されていることがわかります。
重要な日付の合計パーセント値がわかったので、100 を超えないものを除外し、残りを結合しOwnership
て、取得した合計に寄与する所有権の詳細にアクセスできます。したがって、メイン クエリの最終結果は次のようになります。
EventDate TotalPercent PropertyId PersonId StartDate EndDate OwnershipPercent
---------- ------------ ---------- -------- ---------- ---------- ----------------
2011-02-01 110 1 1 2010-01-01 2012-01-01 80
2011-02-01 110 1 2 2011-01-01 2011-03-01 20
2011-02-01 110 1 3 2011-02-01 2011-04-01 10
2011-05-01 120 1 1 2010-01-01 2012-01-01 80
2011-05-01 120 1 4 2011-05-01 2011-07-01 40
SQL Fiddle でこのクエリを確認する (および操作する) こともできます。