以下类似于@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
现在,您可以看到,在反透视的第一步,不仅原始表的每一行都被替换为两行,而且每个百分比值都被标记为增量(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
,同时考虑值是增加还是减少。(实际上,您可以在第一阶段将符号合并到OwnershipPercent
中,而不是分配单独的列PercentFactor
。我选择后者是为了更好地说明这个想法,但如果您更喜欢前者,则应该没有性能损失。)而且这个是计算运行总数后得到的结果(这是第二个 CTE, 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查看(以及玩弄)此查询。