SQL 汇总在一组依据中发生冲突的日期范围

SQL SUM up date ranges that collide on a group by

我有一个 table 列:名称、开始日期(日期值)和完成日期(日期值)。我想按名称对日期进行分组,这样我就可以得到没有冲突的总时间。所以,如果我有一个 table

name | start date | finish date
===============================
a    | 20/10/2015 | 22/10/2015
a    | 21/10/2015 | 22/10/2015
a    | 26/10/2015 | 27/10/2015

因此,如果我按名称分组,则 3 行将聚合,如果我简单地在每行中添加 DATEDIFF 天,我将得到 4,如果我计算 MIN 开始日期和 MAX 完成日期之间的 DATEDIFF将是 7,而实际上正确答案是 3,因为第二行与第一行相撞,我只需要计算一次。

感谢您在下方发表评论。我使用了完全不同的方法。首先,L 构建一个日历 CTE a,其中包含 table 中存在的所有日期。您可以使用数据库中的现有日历 table(如果您有的话)。然后在 CTE b I CROSS JOIN 日历 CTE 中获取日期范围内存在的日期。在此 CTE 中,您有多少重叠范围并不重要,因为日期将仅使用 GROUP BY [name] 子句包含一次。现在您需要做的就是计算 CTE c:

中各个日期的数量

SQL Fiddle

MS SQL Server 2008 架构设置:

CREATE TABLE Table1
    ([name] varchar(1), [start date] datetime, [finish date] datetime)
;

INSERT INTO Table1
    ([name], [start date], [finish date])
VALUES
    ('a', '2015-10-20 00:00:00', '2015-10-22 00:00:00'),
    ('a', '2015-10-21 00:00:00', '2015-10-22 00:00:00'),
    ('a', '2015-10-21 00:00:00', '2015-10-23 00:00:00'),
    ('a', '2015-10-26 00:00:00', '2015-10-27 00:00:00')
;

查询 1:

with dt as(
  select min([start date]) as sd, max([finish date]) as fd from Table1
),
a as (
  select sd from dt
  union all 
  select dateadd(day, 1, a.sd)
  FROM a cross join dt
  where a.sd < fd
),
b as(
  select [name], sd
  from table1 cross join a where a.sd between [start date] and [finish date]
  group by [name], sd
),
c as (
  select [name], count(*) days from b group by [name]
)
select * from c
option (maxrecursion 0)

Results:

| name | days |
|------|------|
|    a |    6 |