假设我们有这样一张桌子:
declare @periods table (
s date,
e date,
t tinyint
);
具有按开始日期(s)排序的无间隔的日期间隔
insert into @periods values
('2013-01-01' , '2013-01-02', 3),
('2013-01-02' , '2013-01-04', 1),
('2013-01-04' , '2013-01-05', 1),
('2013-01-05' , '2013-01-06', 2),
('2013-01-06' , '2013-01-07', 2),
('2013-01-07' , '2013-01-08', 2),
('2013-01-08' , '2013-01-09', 1);
所有日期间隔都有不同的类型 (t)。
需要组合相同类型的日期间隔,它们不会被其他类型的间隔打破(所有间隔都按开始日期排序)。
因此结果表应如下所示:
s | e | t
------------|------------|-----
2013-01-01 | 2013-01-02 | 3
2013-01-02 | 2013-01-05 | 1
2013-01-05 | 2013-01-08 | 2
2013-01-08 | 2013-01-09 | 1
任何想法如何在没有光标的情况下做到这一点?
我有一个可行的解决方案:
declare @periods table (
s datetime primary key clustered,
e datetime,
t tinyint,
period_number int
);
insert into @periods (s, e, t) values
('2013-01-01' , '2013-01-02', 3),
('2013-01-02' , '2013-01-04', 1),
('2013-01-04' , '2013-01-05', 1),
('2013-01-05' , '2013-01-06', 2),
('2013-01-06' , '2013-01-07', 2),
('2013-01-07' , '2013-01-08', 2),
('2013-01-08' , '2013-01-09', 1);
declare @t tinyint = null;
declare @PeriodNumber int = 0;
declare @anchor date;
update @periods
set period_number = @PeriodNumber,
@PeriodNumber = case
when @t <> t
then @PeriodNumber + 1
else
@PeriodNumber
end,
@t = t,
@anchor = s
option (maxdop 1);
select
s = min(s),
e = max(e),
t = min(t)
from
@periods
group by
period_number
order by
s;
但我怀疑我是否可以依赖 UPDATE 语句的这种行为?
我使用 SQL Server 2008 R2。
编辑:
感谢 Daniel 和这篇文章:http ://www.sqlservercentral.com/articles/T-SQL/68467/
我发现上述解决方案中遗漏了三件重要的事情:
- 表上必须有聚集索引
- 必须有锚变量和聚集列的调用
- 更新语句应该由一个处理器执行,即没有并行性
我已根据这些规则更改了上述解决方案。