日期:2014-05-18  浏览次数:20469 次

分享解决连续时间问题的方法
SQL code

--最近在论坛看到过很多关于解决连续时间问题的帖子。关于连续时间问题其实也可以归于孤岛问题。
关于孤岛问题的解决方案我之前发表过一篇帖子,链接如下:


http://topic.csdn.net/u/20120325/17/5a53bd46-8870-450a-a9ca-7ef8661e638d.html
SQL code

--当你看完处理连续数字的问题的解决方案时我相信也就明白了解决连续时间问题的方案,下面我以一种方法实现
/*
name logindate
a1 2011-1-2
a1 2011-1-3
a1 2011-1-4
a1 2011-1-7
a1 2011-1-12
a1 2011-1-13
a1 2011-1-16
a2 2011-1-7
a2 2011-1-8
a2 2011-1-10
a2 2011-1-11
a2 2011-1-13
a2 2011-1-24
---------------------------------------------
我需要的结果是:
name start_day end_day logindays
a1 2011-1-2 2011-1-4 3
a2 2011-1-7 2011-1-8 2
a2 2011-1-10 2011-1-11 2
*/
--------------------------------------------
--> 测试数据:[tbl]
if object_id('[tbl]') is not null drop table [tbl]
create table [tbl]([name] varchar(2),[logindate] date)
insert [tbl]
select 'a1','2011-1-2' union all
select 'a1','2011-1-3' union all
select 'a1','2011-1-4' union all
select 'a1','2011-1-7' union all
select 'a1','2011-1-12' union all
select 'a1','2011-1-13' union all
select 'a1','2011-1-16' union all
select 'a2','2011-1-7' union all
select 'a2','2011-1-8' union all
select 'a2','2011-1-10' union all
select 'a2','2011-1-11' union all
select 'a2','2011-1-13' union all
select 'a2','2011-1-24'

with t as(
select [name],[logindate],(select min(b.[logindate]) from tbl b 
where b.[logindate]>=a.[logindate] and b.name=a.name
and not exists (select * from tbl c
where c.[logindate]=dateadd(dd,1,b.[logindate]) and c.name=b.name)) as grp
from tbl a
),m
as(
select [name],MIN([logindate]) as start_day,MAX(grp) as end_day
from t group by grp,name
)
select *,(DATEDIFF(DD,start_day,end_day)+1) as logindays from m a 
where (DATEDIFF(DD,start_day,end_day)+1) in(
select max(DATEDIFF(DD,start_day,end_day)+1) from m b
where a.name=b.name)
-------------------------
/*
name    start_day    end_day    logindays
a1    2011-01-02    2011-01-04    3
a2    2011-01-07    2011-01-08    2
a2    2011-01-10    2011-01-11    2
*/
-----------------------------
希望能看到有人写出给多的方法哦。谢谢阅读



------解决方案--------------------
感谢分享..

------解决方案--------------------
回复一下,支持分享!
------解决方案--------------------
支持。
------解决方案--------------------
SQL code

create table tb1([name] varchar(2),[logindate] datetime)
insert tb1
select 'a1','2011-1-2' union all
select 'a1','2011-1-3' union all
select 'a1','2011-1-4' union all
select 'a1','2011-1-7' union all
select 'a1','2011-1-12' union all
select 'a1','2011-1-13' union all
select 'a1','2011-1-16' union all
select 'a2','2011-1-7' union all
select 'a2','2011-1-8' union all
select 'a2','2011-1-10' union all
select 'a2','2011-1-11' union all
select 'a2','2011-1-13' union all
select 'a2','2011-1-24'
go

declare @date datetime
select @date = min(logindate) from tb1

;with ach as
(
    select [name],logindate,id=row_number() over (partition by [name] order by logindate)
    from tb1
)

select [name],min(logindate) mindate,max(logindate) maxdate,
    datediff(dd,min(logindate),max(logindate)) dddate
from ach
group by [name],datediff(dd,@date,logindate)-id
order by [name],mindate

drop table tb1

/******************************

name mindate                 maxdate                 dddate
---- ----------------------- ----------------------- -----------
a1   2011-01-02 00:00:00.000 2011-01-04 00:00:00.000 2
a1   2011-01-07 00:00:00.000 2011-01-07 00:00:00.000 0
a1   2011-01-12 00:00:00.000 2011-01-13 00:00:00.000 1
a1   2011-01-16 00:00:00.000 2011-01-16 00:00:00.000 0
a2   2011-01-07 00:00:00.000 2011-01-08 00:00:00.000 1
a2   2011-01-10 00:00:00.000 2011-01-11 00:00:00.000 1
a2   2011-01-13 00:00