ПЕРЕКРЫВАЮЩИЕСЯ ДАТЫ МНОГОКолонн - PullRequest
0 голосов
/ 10 декабря 2018
;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

Это код, который я написал, но я получаю дополнительную строку, т.е. 2-я строка является дополнительной, ожидаемый вывод должен иметь только 1-ю, 3-ю и 4-ю строку в качестве вывода, поэтому, пожалуйста, помогите мне с этим.

Я приложил изображение, показывающее ввод, исключенный вывод и вывод, который я получаю. enter image description here

Ответы [ 2 ]

0 голосов
/ 11 декабря 2018

Я использовал тот же сценарий создания таблицы, как и @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)   )

Вы можете использовать self join и Firs_value и последнее значение в группе, чтобы убедиться, что вы сравниваете в пределах одного и того же идентификатора и перекрывающихся дат.

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
0 голосов
/ 10 декабря 2018

У вас так много результатов в вашем первом 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

...