【问题标题】:Multi - Columns OVERLAPPING DATES多列重叠日期
【发布时间】:2018-12-10 10:09:55
【问题描述】:
;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

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

我附上了一张图片,显示了输入、例外输出和我得到的输出。

【问题讨论】:

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


    【解决方案1】:

    您在第一个 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)
    

    输出:

    【讨论】:

      【解决方案2】:

      我使用@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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多