Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Про пересекающиеся периоды  [new]
ferzmikk
Member

Откуда:
Сообщений: 1414
Здравствуйте!

Есть такая задачка. Есть таблица, где по каждому юр лицу перечисляются список мероприятий, с указанными периодами. Если по какому ту юр лицу присутствуют мероприятие с пересекающими периодами, то выбирается последнее мероприятие. То есть отбрасываем зачеркнутые строки.

Номер мероприятия Код юр лица Дата начала Дата окончания
Номер мероприятия1 00001 01.02.2018 01.02.2018
Номер мероприятия2 00001 03.02.2018 03.02.2018
Номер мероприятия3 00001 03.02.2018 03.02.2018
Номер мероприятия4 00001 06.02.2018 08.02.2018
Номер мероприятия5 00001 08.02.2018 08.02.2018
Номер мероприятия6 00002 01.02.2018 01.02.2018
Номер мероприятия7 00002 08.02.2018 08.02.2018
Номер мероприятия8 00002 06.02.2018 08.02.2018

+SQL-запрос с исходными данными
DECLARE @Таблица table(
	[Номер мероприятия] varchar(20),
	[Код юр лица] varchar(8),	
	[Дата начала] date,
	[Дата окончания] date)
;

INSERT INTO
  @Таблица
VALUES 
('Номер мероприятия1','00001','01.02.2018','01.02.2018'),
('Номер мероприятия2','00001','03.02.2018','03.02.2018'),
('Номер мероприятия3','00001','03.02.2018','03.02.2018'),
('Номер мероприятия4','00001','06.02.2018','08.02.2018'),
('Номер мероприятия5','00001','08.02.2018','08.02.2018'),
('Номер мероприятия6','00002','01.02.2018','01.02.2018'),
('Номер мероприятия7','00002','08.02.2018','08.02.2018'),
('Номер мероприятия8','00002','06.02.2018','08.02.2018')
;

SELECT DISTINCT
	[Код юр лица]
FROM
	@Таблица 

Скажите, каким образом надо решать такую задачу?
13 мар 18, 11:19    [21252223]     Ответить | Цитировать Сообщить модератору
 Re: Про пересекающиеся периоды  [new]
так, например
Guest
select * from @Таблица t1
where not exists(
		select 1 from @Таблица t2 
		where	t1.[Код юр лица]=t2.[Код юр лица] 
			and	(t1.[Дата начала] between t2.[Дата начала] and t2.[Дата окончания] or t1.[Дата окончания] between t2.[Дата начала] and t2.[Дата окончания]) 
			and t1.[Номер мероприятия]<t2.[Номер мероприятия] 
		)


Номер мероприятияКод юр лицаДата началаДата окончания
Номер мероприятия1000012018-01-022018-01-02
Номер мероприятия3000012018-03-022018-03-02
Номер мероприятия5000012018-08-022018-08-02
Номер мероприятия6000022018-01-022018-01-02
Номер мероприятия8000022018-06-022018-08-02
13 мар 18, 11:33    [21252278]     Ответить | Цитировать Сообщить модератору
 Re: Про пересекающиеся периоды  [new]
Kopelly
Member

Откуда: Красноярск
Сообщений: 192
ferzmikk,

With with_number as 
(Select *, row_number() over(
Order by (Select 1) --Критерий по которому определяется последний
) as rn from @Таблица)

Select * From with_number a 
Where not exists (Select 1 From with_number b Where a.[Код юр лица] = b.[Код юр лица] and a.rn<b.rn and a.[Дата начала]<=b.[Дата окончания] and a.[Дата окончания]>=b.[Дата окончания])
13 мар 18, 11:34    [21252281]     Ответить | Цитировать Сообщить модератору
 Re: Про пересекающиеся периоды  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 5553
ferzmikk,

если классически - находите ключи с максимальным значением из списка пересечения по самообъединению, добавляете сроки, которые не пересекаются. Можно, например, объединение слева использовать.
13 мар 18, 11:35    [21252284]     Ответить | Цитировать Сообщить модератору
 Re: Про пересекающиеся периоды  [new]
ferzmikk
Member

Откуда:
Сообщений: 1414
Возможно ли добавить поле, который информирует, что по этому мероприятию было удалено другого мероприятие, которое пересекалось периодом?
13 мар 18, 14:44    [21252854]     Ответить | Цитировать Сообщить модератору
 Re: Про пересекающиеся периоды  [new]
так,
Guest
автор
Возможно ли добавить поле, который информирует, что по этому мероприятию было удалено другого мероприятие, которое пересекалось периодом?

select 
	t1.* 
	
	,case when exists(
					select 1 from @Таблица t2 
					where	t1.[Код юр лица]=t2.[Код юр лица] 
						and	(t1.[Дата начала] between t2.[Дата начала] and t2.[Дата окончания] or t1.[Дата окончания] between t2.[Дата начала] and t2.[Дата окончания]) 
						and t1.[Номер мероприятия]>t2.[Номер мероприятия] 
					)
		then 1
		else 0
	end as flag

from @Таблица t1

where not exists(
		select 1 from @Таблица t2 
		where	t1.[Код юр лица]=t2.[Код юр лица] 
			and	(t1.[Дата начала] between t2.[Дата начала] and t2.[Дата окончания] or t1.[Дата окончания] between t2.[Дата начала] and t2.[Дата окончания]) 
			and t1.[Номер мероприятия]<t2.[Номер мероприятия] 
		)


Номер мероприятияКод юр лицаДата началаДата окончанияflag
Номер мероприятия1000012018-01-022018-01-020
Номер мероприятия3000012018-03-022018-03-021
Номер мероприятия5000012018-08-022018-08-021
Номер мероприятия6000022018-01-022018-01-020
Номер мероприятия8000022018-06-022018-08-021
13 мар 18, 15:02    [21252923]     Ответить | Цитировать Сообщить модератору
 Re: Про пересекающиеся периоды  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 4816
так,,

скупой платит дважды?
13 мар 18, 15:07    [21252942]     Ответить | Цитировать Сообщить модератору
 Re: Про пересекающиеся периоды  [new]
так,
Guest
TaPaK
так,,

скупой платит дважды?
:)

нуу, как-то такое выглядит "сильно пугающе" чем 2-а простых экзиста ...

select 
	t1.* 
	,haba.flag2
from @Таблица t1

outer apply(
		select 
				flag1	=max(case when t3.[Номер мероприятия]<t2.[Номер мероприятия] then 1 else 0 end)
				,flag2	=max(case when t3.[Номер мероприятия]>t2.[Номер мероприятия] then 1 else 0 end)  
		from @Таблица t2 cross join (select t1.[Номер мероприятия] as [Номер мероприятия]) t3
		where	t1.[Код юр лица]=t2.[Код юр лица] 
			and	(t1.[Дата начала] between t2.[Дата начала] and t2.[Дата окончания] or t1.[Дата окончания] between t2.[Дата начала] and t2.[Дата окончания]) 
		) haba

where haba.flag1=0
13 мар 18, 15:18    [21252977]     Ответить | Цитировать Сообщить модератору
 Re: Про пересекающиеся периоды  [new]
Pochemoochka
Guest
и так! :)

Declare @T Table (Title varchar(50), Code varchar(5), DateFrom date, DateTo date)

Insert @T
    Values 
        ('Номер мероприятия1', '00001', '01.02.2018',	'01.02.2018'),
        ('Номер мероприятия2', '00001', '03.02.2018',	'03.02.2018'),
        ('Номер мероприятия3', '00001', '03.02.2018',	'03.02.2018'),
        ('Номер мероприятия4', '00001', '06.02.2018',	'08.02.2018'),
        ('Номер мероприятия5', '00001', '08.02.2018',	'08.02.2018'),
        ('Номер мероприятия6', '00002',	'01.02.2018',	'01.02.2018'),
        ('Номер мероприятия7', '00002',	'08.02.2018',	'08.02.2018'),
        ('Номер мероприятия8', '00002',	'06.02.2018',	'08.02.2018')


    ; with T as
        ( Select *, row_number() Over (Order by Code, DateFrom, DateTo, Title) N 
          From @T
        )
        Select Source.* 
          From T as Source
               Left Join T as Dist
               On Source.DateFrom <= Dist.DateTo and Source.DateTo >= Dist.DateFrom and Source.Code = Dist.Code and Dist.N <> Source.N
         Where Source.N > Dist.N or Dist.N IS NULL
14 мар 18, 17:12    [21256324]     Ответить | Цитировать Сообщить модератору
 Re: Про пересекающиеся периоды  [new]
ferzmikk
Member

Откуда:
Сообщений: 1414
Спасибо!
15 мар 18, 07:26    [21257436]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить