我有一个包含列的表:名称,开始日期(日期值)和完成日期(日期值)。我希望按名称分组,添加日期,以便我得到没有碰撞的总时间。所以,如果我有一张桌子
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,因为第二行与第一行碰撞,我只需要计算一次这个时间。
答案 0 :(得分:0)
感谢您在下面的评论。我使用了一种完全不同的方法。 First L构建一个日历CTE a,其中包含表中存在的所有日期。您可以使用数据库中的现有日历表(如果有)。然后在CTE b I CROSS JOIN日历CTE中获取日期范围的日期。在此CTE中,您拥有多少重叠范围并不重要。日期将仅使用GROUP BY [name]
子句包含一次。现在您需要做的就是计算CTE c中各个日期的数量:
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 |