确定最小连续年份范围的第一年和连续年份的数量

时间:2015-04-16 16:51:02

标签: sql sql-server sql-server-2012

鉴于下表,

 PersonID     Year
---------- ----------
1          1991
1          1992
1          1993
1          1994
1          1996
1          1997
1          1998
1          1999
1          2000
1          2001
1          2002
1          2003
2          1999
2          2000
...        ...

是否有一种方法可以使用SQL select查询来获得最近连续年份的第一年达到最小数量,以及连续几年的总数?在这种情况下,对于personID 1,最少4年,它将返回1996年和8年。

这将加入personID上的另一个表,因此personID不是特定的。

感谢您的帮助。

3 个答案:

答案 0 :(得分:3)

您可以在cte中创建islands of years并检查您的条件:

declare @PersonId int = 1, @cnt int = 4

;with cte_numbered as (
      select
            PersonID,
            [Year],
            row_number() over(partition by PersonID order by [Year]) as rn
      from Table1
), cte_grouped as (
  select
       PersonID, min([Year]) as [Year], count(*) as cnt
  from cte_numbered
  group by PersonID, [Year] - rn
)
select top 1 *
from cte_grouped 
where PersonId = @PersonId and cnt >= @cnt
order by [Year] desc

<强> sql fiddle demo

你也可以做一些更优化的事情,比如这个

declare @PersonId int = 1, @cnt int = 4

;with cte_numbered as (
      select
            PersonID,
            [Year],
            row_number() over(partition by PersonID order by [Year]) as rn
      from Table1
      where personId = @personId
), cte_grouped as (
  select
      row_number() over(partition by [year] - rn order by year) as cnt, year
  from cte_numbered
)
select top 1 cnt, year - cnt + 1
from cte_grouped
where cnt >= @cnt
order by [Year] desc, cnt desc

<强> sql fiddle demo

答案 1 :(得分:1)

使用两个CTE创建行号分组,您可以按PersonID分组并显示它适用的所有personID:

Declare @MinimumConsecutiveYears int=4

;With YearGroupings as (
    Select
        PersonID
        ,year
        ,row_number() over(partition by personid order by year asc) rown
    From @years
)
, ConsecutiveYears as (
    Select 
        PersonID
        ,min(year) as MinYear
        ,count(rown) as ConsecutiveYears
        ,row_number() over(partition by PersonID order by count(rown) desc) rown
    From YearGroupings
    Group By PersonID,year-rown
    Having Count(rown)>@MinimumConsecutiveYears
)
Select PersonID,MinYear,ConsecutiveYears
From ConsecutiveYears
Where Rown=1

或者,没有CTE:

Declare @MinimumConsecutiveYears int=4

Select
    PersonID
    ,year
    ,row_number() over(partition by personid order by year asc) rown
Into #YearGroupings
From #years

Select 
    PersonID
    ,min(year) as MinYear
    ,count(rown) as ConsecutiveYears
    ,row_number() over(partition by PersonID order by count(rown) desc) rown
Into #ConsecutiveYears 
From YearGroupings
Group By PersonID,year-rown
Having Count(rown)>@MinimumConsecutiveYears

Select PersonID,MinYear,ConsecutiveYears
From #ConsecutiveYears
Where Rown=1

答案 2 :(得分:1)

试试这个:

declare @minnumber int
set @minnumber = 4

declare @personid int
set @personid = 0

select orig.[PersonID], min(orig.[Year]) as FirstYear ,count(*) as TCYears
from --add rownumber, sorted by year column
(
    SELECT ROW_NUMBER() 
        OVER (Partition by [PersonID] ORDER BY [Year]) AS Row,*
        from Table1
    where PersonID = @personid
) orig
where orig.PersonID = @personid
and orig.Row > @minnumber --
group by orig.PersonID