SQL计算日期范围内的连续天数

时间:2020-10-20 13:14:16

标签: sql sql-server datetime count gaps-and-islands

我正在尝试计算一个人可能拥有的连续天数,唯一的问题是我有日期范围,而不是日期的直接列表。这是我所说的范围的示例:

Name    Start_Date  End_Date
Johnny  2020-01-02  2020-01-04
Johnny  2020-01-05  2020-01-05
Johnny  2020-01-06  2020-01-10
Jenny   2020-02-07  2020-02-07
Jenny   2020-02-10  2020-02-11
Jenny   2020-02-12  2020-02-12

开始日期和结束日期在2列之内。

我想要达到的结果是:

Johnny has 9 consecutive days
Jenny  has 3 consecutive days

我遇到了一些解决方案的示例,但是找不到适合日期范围的问题。

到目前为止使用的代码示例:

WITH
 
  dates(date, employee_number) AS (
    SELECT DISTINCT CAST(start_date AS DATE), name
    FROM myTABLE
    WHERE name = "Jenny"

  ),
   
  groups AS (
    SELECT
      ROW_NUMBER() OVER (ORDER BY date) AS rn, name,
      dateadd(day, -ROW_NUMBER() OVER (ORDER BY date), date) AS grp,
      date
    FROM dates
  )
SELECT
  name,
  COUNT(*) AS consecutiveDates,
  MIN(date) AS minDate,
  MAX(date) AS maxDate
FROM groups
GROUP BY grp, name

2 个答案:

答案 0 :(得分:3)

这是一个空白问题。一种选择是使用lag()和窗口sum()来构建相邻记录的组。然后,您可以按组汇总并计算连续天数,最后按名称过滤最大的条纹:

select name, max(consecutive_days) consecutive_days
from (
    select name, datediff(day, min(start_date), max(end_date)) + 1 consecutive_days
    from (
        select t.*, 
            sum(case when start_date = dateadd(day, 1, lag_end_date) then 0 else 1 end) over(partition by name order by start_date) grp
        from (
            select t.*, 
                lag(end_date) over(partition by name order by start_date) lag_end_date
            from mytable t
        ) t
    ) t
    group by name, grp
) t
group by name

Demo on DB Fiddle

name   | consecutive_days
:----- | ---------------:
Jenny  |                3
Johnny |                9

答案 1 :(得分:0)

类似的事情应该起作用。用表格替换子选择。

select name, DATEDIFF(dd, MIN(Start_date),MAX(end_date)) +1 from 

(
select a.name,a.start_date,b.end_date from 
(SELECT 'Johnny' name , '2020-01-02' start_date,  '2020-01-04' end_date
UNION SELECT 'Johnny' , '2020-01-05',  '2020-01-05'
UNION SELECT 'Johnny' , '2020-01-06',  '2020-01-10'
UNION SELECT 'Jenny'  , '2020-02-07',  '2020-02-07'
UNION SELECT 'Jenny'  , '2020-02-10',  '2020-02-11'
UNION SELECT 'Jenny'  , '2020-02-12',  '2020-02-12') a
LEFT join (SELECT 'Johnny' name , '2020-01-02' start_date,  '2020-01-04' end_date
UNION SELECT 'Johnny' , '2020-01-05',  '2020-01-05'
UNION SELECT 'Johnny' , '2020-01-06',  '2020-01-10'
UNION SELECT 'Jenny'  , '2020-02-07',  '2020-02-07'
UNION SELECT 'Jenny'  , '2020-02-10',  '2020-02-11'
UNION SELECT 'Jenny'  , '2020-02-12',  '2020-02-12') b on DATEADD(dd,1,a.end_date ) = b.start_date and a.name = b.name
)q

group by name