SQL SUM更新日期范围在组中发生冲突

时间:2015-12-10 23:55:49

标签: sql sql-server-2008 group-by sum sqldatetime

我有一个包含列的表:名称,开始日期(日期值)和完成日期(日期值)。我希望按名称分组,添加日期,以便我得到没有碰撞的总时间。所以,如果我有一张桌子

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,因为第二行与第一行碰撞,我只需要计算一次这个时间。

1 个答案:

答案 0 :(得分:0)

感谢您在下面的评论。我使用了一种完全不同的方法。 First L构建一个日历CTE a,其中包含表中存在的所有日期。您可以使用数据库中的现有日历表(如果有)。然后在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 |