SQL Server:Gap / Island,365天“连续”块

时间:2014-03-17 08:54:28

标签: sql-server gaps-and-islands

我有一张如下表: -

tblMeterReadings

  

ID米日期总
  1 1 2014年3月1日100.1
  1 1 2014年4月1日184.1
  1 1 2014年5月1日134.1
  1 1 2014年6月1日132.1
  1 1 07/01/2014 126.1
  1 1 08/01/2014 190.1

这是来自'2014-01-03' to '2014-01-08'的8天“连续区块”。

在真实表格中,存在多年的“连续块”。

我需要选择 MOST RESCENT CONTINUOUS 365 DAY BLOCK (按米列筛选)。如果找不到365,则应选择下一个最大的连续块。

当我说连续时,我的意思是一定不会缺少任何日子。

这超出了我的范围,所以如果有人可以解决......我会非常感动。

3 个答案:

答案 0 :(得分:0)

使用递归CTEdatepart(dayofyear, date)

with cte as
(
  select id, meter, date, datepart(dayofyear, date) as x, cast(1 as int) as level, t1.date as startDate from tblMeterReadings t1
    where meter = 1 
      and not exists(select * from tblMeterReadings t2 where (datepart(dayofyear, t1.date) - 1) = datepart(dayofyear, t2.date))
  union all
  select t1.id, t1.meter, t1.date, datepart(dayofyear, t1.date) as x, t2.level + 1, t2.startDate from tblMeterReadings t1
   inner join cte t2 ON (datepart(dayofyear, t1.date)) = (datepart(dayofyear, t2.date) + 1)      
)    
select TOP 365 * from cte
where cte.startDate = (select top 1 startdate 
                       from cte 
                       --where Level <= 365 
                       order by Level desc, startDate desc)
order by Level desc
OPTION ( MAXRECURSION 365 )

SQL Fiddle example

答案 1 :(得分:0)

你去了:

declare @tblMeterReadings table (id int, meter int, [date] date, total money)

insert into @tblMeterReadings ( id, meter, date, total )
values
    (1, 1, '03/01/2014', 100.1),
    (1, 1, '04/01/2014', 184.1),
    (1, 1, '05/01/2014', 134.1),
    (1, 1, '06/01/2014', 132.1),
    (1, 1, '07/01/2014', 126.1),
    (1, 1, '08/01/2014', 190.1),
    (1, 1, '10/01/2014', 200.1),
    (1, 1, '12/01/2014', 202.1),
    (1, 1, '13/01/2014', 204.1)

;with data as (
    select i = datediff(day, '2014', [date]), * 
    from @tblMeterReadings l
)
, islands as (
    select island = l.i - row_number() over (order by i), l.*
    from data l 
)
, spans as (
    select l = min(i), r = max(i)
    from islands i
    group by island
)
select * 
from spans s
left join data l on s.l = l.i
left join data r on s.r = r.i

最近不超过365天的连续区块如下:

select top 1 *
from spans s
left join data l on s.l = l.i
left join data r on s.r = r.i
where s.l - s.r < 365
order by s.l - s.r desc, s.r desc

答案 2 :(得分:0)

使用distinct来计算带有2组数据的天数

declare @gapdays int = 2 -- replace this with 365 in your case

;with x as
(
  select datediff(d, '2014-01-01', [date])-dense_rank()over(order by [date])  grp
         ,[date]
  from @t
)
select top 1 max([date]) last_date, min([date]) first_date, count(distinct [date]) days_in_a_row
from x
group by grp
having count(distinct [date]) >= @gapdays
order by max([date]) desc