问题描述
输入:
id startdate enddate
1 21/01/2019 23/01/2019
1 23/01/2019 24/01/2019
1 24/01/2029 27/01/2019
1 29/01/2019 02/02/2019
输出:
id startdate enddate
1 21/01/2019 27/01/2019
1 29/01/2019 02/02/2019
我们需要使用匹配第一条记录enddate
和第n条记录startdate
的逻辑。
解决方法
这是一个空白问题,您希望将“相邻”日期分组在一起。这是使用窗口函数的一种方法:想法是将当前开始日期与“上一个”行的结束日期进行比较,并使用窗口总和来定义组:
select id,min(startdate) startdate,max(enddate) enddate
from (
select t.*,sum(case when startdate = lag_enddate then 0 else 1 end) over(partition by id order by startdate) grp
from (
select t.*,lag(enddate) over(partition by id order by startdate) lag_enddate
from mytable t
) t
) t
group by id,grp
Demo on DB Fiddle -首先感谢Sander用于创建DDL语句:
id | startdate | enddate -: | :--------- | :--------- 1 | 2019-01-21 | 2019-01-27 1 | 2019-01-29 | 2019-02-02,
看看
-
NEXT VALUE FOR方法,在2016年及以后可用
-
使用CTE或子查询(在2008年可用),在其中使用前一个值作为联接在自己的表上联接。这是我用来显示备份增长的示例脚本
declare @backupType char(1),@DatabaseName sysname set @DatabaseName = db_name() --> Name of current database,null for all databaseson server set @backupType ='D' /* valid options are: D = Database I = Database Differential L = Log F = File or Filegroup G = File Differential P = Partial Q = Partial Differential */ select backup_start_date,backup_finish_date,DurationSec,database_name,backup_size,PreviouseBackupSize,backup_size-PreviouseBackupSize as growth,KbSec= format(KbSec,'N2') FROM ( select backup_start_date,datediff(second,backup_start_date,b.backup_finish_date) as DurationSec,b.database_name,b.backup_size/1024./1024. as backup_size,case when datediff(second,b.backup_finish_date) >0 then ( b.backup_size/1024.)/datediff(second,b.backup_finish_date) else 0 end as KbSec --,b.compressed_backup_size,( select top (1) p.backup_size/1024./1024. from msdb.dbo.backupset p where p.database_name = b.database_name and p.database_backup_lsn< b.database_backup_lsn and type=@backupType order by p.database_backup_lsn desc ) as PreviouseBackupSize from msdb.dbo.backupset as b where @DatabaseName IS NULL OR database_name =@DatabaseName and type=@backupType )as A order by backup_start_date desc
-
使用“ cursor local fast_forward”游标逐行遍历数据,并使用临时表存储和保留先前的值
这是一个可行的通用表表达式解决方案。
样本数据
create table data
(
id int,startdate date,enddate date
);
insert into data (id,startdate,enddate) values
(1,'2019-01-21','2019-01-23'),(1,'2019-01-23','2019-01-24'),'2019-01-24','2019-01-27'),'2019-01-29','2019-02-02');
解决方案
-- determine start dates
with cte_start as
(
select s.id,s.startdate
from data s
where not exists ( select 'x'
from data e
where e.id = s.id
and e.enddate = s.startdate )
),-- determine date boundaries
cte_startnext as
(
select s.id,s.startdate,lead(s.startdate) over (partition by s.id order by s.startdate) as startdate_next
from cte_start s
)
-- determine periods
select sn.id,sn.startdate,e.enddate
from cte_startnext sn
cross apply ( select top 1 e.enddate
from data e
where e.id = sn.id
and e.startdate >= sn.startdate
and (e.startdate < sn.startdate_next or sn.startdate_next is null)
order by e.enddate desc ) e
order by sn.id,sn.startdate;
结果
id startdate enddate
-- ---------- ----------
1 2019-01-21 2019-01-27
1 2019-01-29 2019-02-02
Fiddle查看解决方案和中间CTE结果的建立。