【问题标题】:SQL Counting Consecutive Days in Date RangesSQL 计算日期范围内的连续天数
【发布时间】:2021-02-03 07:52:58
【问题描述】:

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

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

【问题讨论】:

  • 您使用的是哪个数据库? MySQLsql-server,指定一个。
  • 嗨,我正在使用 sql-server
  • 你能给我们举个例子来说明你迄今为止的尝试吗?
  • @holder 我用我一直在使用的代码示例编辑了我的问题

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


【解决方案1】:

这是一个孤岛问题。一种选择是使用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

姓名 |连续多日 :----- | ---------------: 珍妮 | 3 强尼 | 9

【讨论】:

    【解决方案2】:

    这样的事情应该可以工作。用您的表格替换子选择。

    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
    

    【讨论】:

      猜你喜欢
      • 2011-02-05
      • 1970-01-01
      • 2019-04-12
      • 1970-01-01
      • 1970-01-01
      • 2019-12-04
      • 2013-12-15
      • 2018-12-15
      • 1970-01-01
      相关资源
      最近更新 更多