我想知道如何在sql中进行相邻日期范围的交叉或连接。
我有一个客户开始和结束日期列表,例如(以dd / mm / yyyy格式,其中31/12/9999表示客户仍然是当前客户)。
CustID | StartDate | Enddate |
1 | 01/08/2011|19/06/2012|
1 | 20/06/2012|07/03/2012|
1 | 03/05/2012|31/12/9999|
2 | 09/03/2009|16/08/2009|
2 | 16/01/2010|10/10/2010|
2 | 11/10/2010|31/12/9999|
3 | 01/08/2010|19/08/2010|
3 | 20/08/2010|26/12/2011|
虽然不同行中的日期不重叠,但我会将某些范围视为一个有争议的时间段,例如,当开始日期是结束日期后一天(对于给定的客户)。因此,我想返回一个只返回日期交集的查询
CustID | StartDate | Enddate |
1 | 01/08/2011|07/03/2012|
1 | 03/05/2012|31/12/9999|
2 | 09/03/2009|16/08/2009|
2 | 16/01/2010|31/12/9999|
3 | 01/08/2010|26/12/2011|
我查看了CTE表,但我无法弄清楚如何为一个连续的日期块返回一行。
答案 0 :(得分:1)
这应该在2005年推进:
;WITH cte2 AS (SELECT 0 AS Number
UNION ALL
SELECT Number + 1
FROM cte2
WHERE Number < 10000)
SELECT CustID, Min(GroupStart) StartDate, MAX(EndDate) EndDate
FROM (SELECT *
, DATEADD(DAY,b.number,a.StartDate) GroupStart
, DATEADD(DAY,1- DENSE_RANK() OVER (PARTITION BY CustID ORDER BY DATEADD(DAY,b.number,a.StartDate)),DATEADD(DAY,b.number,a.StartDate)) GroupDate
FROM Table1 a
JOIN cte2 b
ON b.number <= DATEDIFF(d, startdate, EndDate)
) X
GROUP BY CustID, GroupDate
ORDER BY CustID, StartDate
OPTION (MAXRECURSION 0)
演示:SQL Fiddle
您可以构建一个数字0的快速表,其大小足以覆盖范围中日期的范围以替换cte,因此它不会每次运行,正确索引它将快速运行。
答案 1 :(得分:0)
您可以使用recursive common table expression执行此操作:
with cte as (
select t.CustID, t.StartDate, t.EndDate, t2.StartDate as NextStartDate
from Table1 as t
left outer join Table1 as t2 on t2.CustID = t.CustID and t2.StartDate = case when t.EndDate < '99991231' then dateadd(dd, 1, t.EndDate) end
), cte2 as (
select c.CustID, c.StartDate, c.EndDate, c.NextStartDate
from cte as c
where c.NextStartDate is null
union all
select c.CustID, c.StartDate, c2.EndDate, c2.NextStartDate
from cte2 as c2
inner join cte as c on c.CustID = c2.CustID and c.NextStartDate = c2.StartDate
)
select CustID, min(StartDate) as StartDate, EndDate
from cte2
group by CustID, EndDate
order by CustID, StartDate
option (maxrecursion 0);
<强> sql fiddle demo 强>
快速性能测试:
750 行的结果,小周期的2天长度:
<强> sql fiddle demo 强>
5 行的结果,大周期:
<强> sql fiddle demo 强>