我有一张这样的表
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 :(得分:2)
这个问题名为“缺口和岛屿问题”。我不能在这里发表答案,所以我创造了小提琴:
<强> SQL FIDDLE 强>
答案 1 :(得分: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。
更新:LEAD
可从SQL Server 2012开始提供,因此虽然它适用于OP的情况,但它不适用于旧版本。