抱歉,您最后的评论回复缓慢;周末开始时我一直在工作/离开。你所追求的可以根据我之前的回答来实现,但我怀疑下面的代码会更有效率/可读性。以下代码的缺点是它确实依赖于新的 SQL 2012 LAG 和 LEAD 功能。
您可以在此处阅读这些功能:http: //blog.sqlauthority.com/2011/11/15/sql-server-introduction-to-lead-and-lag-analytic-functions-introduced-in-sql-server -2012/
如果您选择升级,请在此处了解有关 SQL 2012 许可的信息:http: //www.microsoft.com/sqlserver/en/us/get-sql-server/how-to-buy.aspx
显然,升级可能不合理的原因有很多,但我想我会提供这个答案,以防您/其他寻求此解决方案的人可以选择:
--Sample Data Setup:
if object_id('demo') is not null drop table demo
go
create table demo
(
id bigint identity(1,1) not null primary key clustered
, groupId nchar not null
, startDate date not null constraint uk_demo_startDate unique
)
go
insert demo
select 'A', '2009-01-01'
union all select 'A', '2009-01-02'
union all select 'A', '2009-02-01'
union all select 'B', '2009-03-01'
union all select 'B', '2009-04-01'
union all select 'B', '2009-05-01'
union all select 'C', '2009-06-01'
union all select 'C', '2009-07-01'
union all select 'C', '2009-08-01'
union all select 'A', '2009-09-01'
union all select 'A', '2009-10-01'
union all select 'A', '2009-11-01'
union all select 'A', '2009-12-01'
union all select 'C', '2010-01-01'
union all select 'D', '2010-01-02'
union all select 'D', '2010-01-03'
union all select 'D', '2010-01-04'
union all select 'E', '2010-01-05'
union all select 'E', '2010-01-06'
union all select 'D', '2010-01-07'
union all select 'D', '2010-01-08'
union all select 'E', '2010-01-09'
union all select 'E', '2010-01-10'
union all select 'D', '2011-01-01'
union all select 'D', '2011-01-02'
union all select 'E', '2012-01-01'
union all select 'X', '2012-01-02'
union all select 'D', '2012-01-03'
go
--Actual Solution
select *
, noDays + noDaysAtStatusAtStart noDaysAtStatusAtEnd
from
(
select id
, groupId
, startDate
, noDays
, case
when groupId = previousGroupId then lag(noDays,1) over (order by startDate)
--when previousGroupId is null then 0 --covered by else
else 0
end noDaysAtStatusAtStart
from
(
select id
, startDate
, groupId
, endDate
, previousGroupId
, dateDiff(day,startDate,endDate) noDays
from
(
select id
, startDate
, groupId
, lead(startDate,1) over (order by startDate) endDate
, lag(groupId,1) over (order by startDate) previousGroupId
from demo
) x
) y
) z
order by z.startDate