1

我有一个包含列的表:名称、开始日期(日期值)和完成日期(日期值)。我想按名称组合日期,这样我就可以得到没有冲突的总时间。所以,如果我有一张桌子

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,因为第二行与第一行发生冲突,我只需要计算一次。

4

1 回答 1

0

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

SQL小提琴

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)

结果

| name | days |
|------|------|
|    a |    6 |
于 2015-12-11T00:51:30.680 回答