多列重叠日期

时间:2018-12-10 10:09:56

标签: sql-server tsql join common-table-expression

;with cte as (
 select Domain_Id, Starting_Date, End_Date
 from Que_Date
 union all
 select t.Domain_Id, cte.Starting_Date, t.End_Date
 from cte
 join Que_Date t on cte.Domain_Id = t.Domain_Id and cte.End_Date = t.Starting_Date),
cte2 as (
 select *, rn = row_number() over (partition by Domain_Id, End_Date order by Domain_Id)
 from cte
)
select DISTINCT Domain_Id, Starting_Date, max(End_Date) enddate
from cte2
where rn=1
group by Domain_Id, Starting_Date
order by Domain_Id, Starting_Date;

select * from Que_Date

这是我编写的代码,但是我得到了额外的一行,即第二行是多余的,预期的输出应该只有第一行,第三行和第四行作为输出,所以请帮助我。

我已附上一张图片,显示输入,排除的输出以及我得到的输出。enter image description here

2 个答案:

答案 0 :(得分:0)

您的第一个cte有很多结果。您的第一个cte具有包含域。因此,您无法基于cte来过滤域。因此,您的查询中有不必要的行。

尝试此解决方案。 Cte ConsistentDomains仅具有一致的域。因此,基于此CTE,我们不会得到重叠的结果。

创建并填充数据:

CREATE TABLE FooTable
(
    Domain_ID INT,
    Starting_Date DATE,
    End_Date Date
)

INSERT INTO dbo.FooTable
(
    Domain_ID,
    Starting_Date,
    End_Date
)
VALUES
(   1,         -- Domain_ID - int
    CONVERT(datetime,'01-01-2011',103), -- Starting_Date - date
    CONVERT(datetime,'05-01-2011',103)  -- End_Date - date
    )
, (1, CONVERT(datetime,'05-01-2011',103), CONVERT(datetime,'07-01-2011',103))
, (1, CONVERT(datetime,'07-01-2011',103), CONVERT(datetime,'15-01-2011',103))
, (2, CONVERT(datetime,'11-05-2011',103), CONVERT(datetime,'12-05-2011',103))
, (2, CONVERT(datetime,'13-05-2011',103), CONVERT(datetime,'14-05-2011',103))

查询以查找不重叠的结果:

DECLARE @startDate varchar(50) = '2011-01-01';
WITH ConsistentDomains AS
(
    SELECT      
      f.Domain_ID
    , f.Starting_Date
    , f.End_Date    
    FROM FooTable f
    WHERE f.Starting_Date = @startDate
    UNION ALL
    SELECT 
      s.Domain_ID
    , s.Starting_Date
    , s.End_Date
    FROM FooTable s
    INNER JOIN  ConsistentDomains cd 
      ON s.Domain_ID = cd.Domain_ID
      AND s.Starting_Date = cd.End_Date
), ConsistentDomainsRownumber AS 
(
    SELECT 
      cd.Domain_ID
    , cd.Starting_Date
    , cd.End_Date
    , ROW_NUMBER() OVER (PARTITION BY cd.Domain_ID ORDER BY cd.Starting_Date, 
        cd.End_Date) RN
    FROM ConsistentDomains cd
)
SELECT cd.Domain_ID
, convert(varchar, cd.Starting_Date, 105) Starting_Date
, convert(varchar, cd.End_Date, 105) End_Date
FROM ConsistentDomainsRownumber cd WHERE  cd.RN = 1
UNION ALL
SELECT        
   ft.Domain_ID
   , convert(varchar, ft.Starting_Date, 105) Starting_Date
   , convert(varchar, ft.End_Date, 105) End_Date
 FROM dbo.FooTable ft WHERE ft.Domain_ID NOT IN (SELECT cd.Domain_ID FROM 
     ConsistentDomainsRownumber cd)

输出:

enter image description here

答案 1 :(得分:0)

我使用了与@stepup提供的表创建脚本相同的脚本,但是您也可以通过这种方式获得结果。

CREATE TABLE testtbl
(
Domain_ID INT,
Starting_Date DATE,
End_Date Date
)

INSERT INTO testtbl

VALUES
(1, convert(date, '01-01-2011' ,103), convert(date, '05-01-2011',103)  )
,(1,  convert(date, '05-01-2011' ,103), convert(date, '07-01-2011',103)  )  
,(1,  convert(date, '07-01-2011' ,103), convert(date, '15-01-2011',103)  )
,(2, convert(date, '11-05-2011' ,103), convert(date, '12-05-2011',103)   )
,(2, convert(date, '13-05-2011' ,103), convert(date, '14-05-2011',103)   )

您可以利用自我联接和Firs_value以及组中的最后一个值来确保您在相同的ID和重叠的日期内进行比较。

select distinct t.Domain_ID,
case when lag(t1.starting_date)over (partition by t.Domain_id order by 
t.starting_date) is not null   
then first_value(t.Starting_Date) over (partition by t.domain_id order by 
t.starting_date) 
else  t.Starting_Date end StartingDate, 
case when lead(t.domain_id) over (partition by t.domain_id order by t.starting_date)  = 
t1.Domain_ID then  isnull(last_value(t.End_Date) over (partition by t.domain_id  order by t.end_date rows between unbounded preceding and unbounded following),t.End_Date)   
else t.End_Date  end    end_date 
from testtbl t 
left join testtbl t1 on t.Domain_ID = t1.Domain_ID 
                    and t.End_Date = t1.Starting_Date 
                    and t.Starting_Date < t1.Starting_Date 

输出:

Domain_ID   StartingDate    end_date
1           2011-01-01  2011-01-15
2           2011-05-11  2011-05-12
2           2011-05-13  2011-05-14