Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 查找两个日期段之间的重叠天数_Sql Server_Tsql - Fatal编程技术网

Sql server 查找两个日期段之间的重叠天数

Sql server 查找两个日期段之间的重叠天数,sql-server,tsql,Sql Server,Tsql,我有两个表,每个表都包含从date1到date2的日期周期 我将在表1和表2中找到两段日期之间的重叠天数 范例 table1 ------------------------- id | FromDate | ToDate 1 |2000-01-01 | 2000-02-04 2 |2000-03-01 | 2000-03-29 table2 ------------------------- id | FromDate | ToDate 1 |2000-02-0

我有两个表,每个表都包含从date1到date2的日期周期

我将在表1和表2中找到两段日期之间的重叠天数

范例

table1
-------------------------
id   |  FromDate | ToDate
1    |2000-01-01 | 2000-02-04
2    |2000-03-01 | 2000-03-29

table2
-------------------------
id   | FromDate  | ToDate
1    |2000-02-01 | 2000-02-07
2    |2000-03-27 | 2000-03-29
我想要的结果是:

2000-02-01
2000-02-02
2000-02-03
2000-02-04
2000-03-27
2000-03-28
2000-03-29
这应该起作用:

CREATE TABLE #t1 
(
  id int,
  FromDate date,
  ToDate date
)
CREATE TABLE #t2
(
  id int,
  FromDate date,
  ToDate date
)

INSERT #t1 VALUES 
(1, '2000-01-01', '2000-02-04'),
(2, '2000-03-01', '2000-03-29')

INSERT #t2 VALUES 
(1, '2000-02-01', '2000-02-07'),
(2, '2000-03-27', '2000-03-29')

WITH DateRange AS --select range where intersection is possible
(
    SELECT MAX(MinDate) MinDate,MIN(MaxDate) MaxDate,DATEDIFF(DAY,MAX(MinDate),MIN(MaxDate)) Diff
    FROM (VALUES ((SELECT MIN(FromDate) FROM #t1)),((SELECT MIN(FromDate) FROM #t2))) MinDate(MinDate)
    CROSS APPLY (VALUES ((SELECT MAX(ToDate) FROM #t1)),((SELECT MAX(ToDate) FROM #t2))) MaxDate(MaxDate)
), AllDates AS --generate sequence of days
(
    SELECT MinDate D, MaxDate Limit
    FROM DateRange
    UNION ALL
    SELECT DATEADD(DAY, 1, D), Limit
    FROM AllDates
    WHERE DATEADD(DAY, 1, D)<=Limit
) --select all days existing in any range in both tables
SELECT D
FROM AllDates
WHERE EXISTS (SELECT * FROM #t1 WHERE D>=FromDate AND D<=ToDate)
  AND EXISTS (SELECT * FROM #t2 WHERE D>=FromDate AND D<=ToDate)

一种可能的解决方案是使用数字或理货表

;WITH cteNumbers (N) 
AS(   
    SELECT ROW_NUMBER() OVER(ORDER BY N1.N) 
    FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N1(N)
    CROSS JOIN (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N2 (N)
    CROSS JOIN (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N3 (N)
)
SELECT T1.FromDate
FROM(
    SELECT
        T1.FromDate
    FROM dbo.Table1 T1
    UNION
    SELECT
        DATEADD(DAY, N, T1.FromDate)
    FROM
        dbo.Table1 T1
    CROSS APPLY cteNumbers N
    WHERE N <= DATEDIFF(DAY, T1.FromDate, T1.ToDate)
) T1
WHERE t1.FromDate IN 
(
    SELECT
        T2.FromDate
    FROM dbo.Table2 T2 
    UNION 
    SELECT
        DATEADD(DAY, N, T2.FromDate)
    FROM
        dbo.Table2 T2
    CROSS APPLY cteNumbers N
    WHERE N <= DATEDIFF(DAY, T2.FromDate, T2.ToDate)
) 

数字/理货表将允许最长1000天的日期范围。如果您需要更多,然后再添加另一行,像这样,交叉连接值1,1,1,1,1,1,1,1 N4 N

可以使用CTE和递归执行此操作

--Your sample data
DECLARE @table1 TABLE (id int PRIMARY KEY, FromDate date, ToDate date)
DECLARE @table2 TABLE (id int PRIMARY KEY, FromDate date, ToDate date)
INSERT INTO @table1 VALUES (1, '2000-01-01', '2000-02-04') , (2, '2000-03-01', '2000-03-29')
INSERT INTO @table2 VALUES (1, '2000-02-01', '2000-02-07') , (2, '2000-03-27', '2000-03-29')

--A couple CTE's
;WITH cteDates AS (        
SELECT T1.id --get the min and max dates for each id
      ,CASE WHEN T1.FromDate > T2.FromDate THEN T1.FromDate ELSE T2.FromDate END [mindate]
      ,CASE WHEN T1.ToDate < T2.ToDate THEN T1.ToDate ELSE T2.ToDate END [maxdate]    
  FROM @table1 T1 INNER JOIN @table2 T2 ON T1.id = T2.id
)

, cteRecursion AS ( --date range for each id
SELECT id, mindate AS DateValue
  FROM cteDates

UNION ALL

SELECT id, DATEADD(DAY, 1, DateValue)
  FROM cteRecursion C1
 WHERE DATEADD(DAY, 1, DateValue) <= (
                                       SELECT maxDate 
                                         FROM cteDates C2
                                        WHERE C2.id = C1.id
                                     )
)

--SELECT query
SELECT DateValue FROM cteRecursion ORDER BY DateValue OPTION (MAXRECURSION 0)

周期是否可以在单个表中重叠,例如1月的第一周和1月的第一个月?表之间是否可以重叠两行以上,例如表1中的1月第一周和最后一周以及表2中的1月?你试过什么?
--Your sample data
DECLARE @table1 TABLE (id int PRIMARY KEY, FromDate date, ToDate date)
DECLARE @table2 TABLE (id int PRIMARY KEY, FromDate date, ToDate date)
INSERT INTO @table1 VALUES (1, '2000-01-01', '2000-02-04') , (2, '2000-03-01', '2000-03-29')
INSERT INTO @table2 VALUES (1, '2000-02-01', '2000-02-07') , (2, '2000-03-27', '2000-03-29')

--A couple CTE's
;WITH cteDates AS (        
SELECT T1.id --get the min and max dates for each id
      ,CASE WHEN T1.FromDate > T2.FromDate THEN T1.FromDate ELSE T2.FromDate END [mindate]
      ,CASE WHEN T1.ToDate < T2.ToDate THEN T1.ToDate ELSE T2.ToDate END [maxdate]    
  FROM @table1 T1 INNER JOIN @table2 T2 ON T1.id = T2.id
)

, cteRecursion AS ( --date range for each id
SELECT id, mindate AS DateValue
  FROM cteDates

UNION ALL

SELECT id, DATEADD(DAY, 1, DateValue)
  FROM cteRecursion C1
 WHERE DATEADD(DAY, 1, DateValue) <= (
                                       SELECT maxDate 
                                         FROM cteDates C2
                                        WHERE C2.id = C1.id
                                     )
)

--SELECT query
SELECT DateValue FROM cteRecursion ORDER BY DateValue OPTION (MAXRECURSION 0)
DateValue
---------
2000-02-01
2000-02-02
2000-02-03
2000-02-04
2000-03-27
2000-03-28
2000-03-29