2014-06-16 195 views
0

我有这样TSQL:结合日期范围

date  | rate 
2014-01-01 | 100 
2014-01-02 | 100 
2014-01-03 | 1 
2014-01-04 | 1 
2014-01-05 | 100 
2014-01-06 | 100 
2014-01-07 | 1 
2014-01-08 | 1 
2014-01-09 | 100 
2014-01-10 | 100 
2014-01-11 | 100 
2014-01-12 | 100 

表我想获得以下

date start  | date end | rate 
2014-01-01  | 2014-01-02 | 100 
2014-01-03  | 2014-01-04 | 1 
2014-01-05  | 2014-01-06 | 100 
2014-01-07  | 2014-01-08 | 1 
2014-01-09  | 2014-01-12 | 100 

等。当然,数字可能会有所不同。

我该如何在TSQL中做到这一点?为了以防万一,我使用了SQL Server 2012。

+0

是日期列连续? –

+0

是的,它包含几年的利率。这是一天一次的费用。 –

+0

最后一个例子不是连续的,即所有先前的增量都是2天,最后一个增加4个。是你预先定义的范围(可能是不同的),还是你总是期望它们遵循一个模式? – sarin

回答

2

这个问题命名为“间隙和孤岛问题”。我不能在这里发表的答案,所以我创建了小提琴:

SQL FIDDLE

0

试试这个:

;with cte as 
(select [date] d,rate, case when lead(rate, 1, 0) over (order by [date]) = rate then 1 else 0 end ld 
from tbl), 

filtered as 
(select *, rank() over (partition by ld order by d) rn 
from cte) 

select f.d [date start], s.d [date end], f.rate 
from filtered f 
inner join filtered s on f.rn = s.rn 
and f.ld = 1 and s.ld = 0 

哈姆雷特的答案是当然的,正确的。我想提出一个替代解决方案。我们使用LEAD分析函数来确定新值范围的开始,然后使用RANK来获取与每个范围所需的开始和结束日期对应的行。

演示here

UPDATELEAD可从SQL Server 2012开始使用,所以虽然它可以在OP的情况下工作,但它不适用于旧版本。

+2

重新检查结果。 –

+0

@HamletHakobyan感谢您指出我以前的查询中的错误。我现在更新了它。 –

+1

值得一提的是'LEAD'只支持SQL Server 2012以上版本。 – adaskos