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

Откуда:
Сообщений: 27
Дана таблица
Dogovors(
	Client_id	int 	not null 	-- клиент
	,type_id	int 	not null		-- тип договора
	,first_date	date	not null		-- первый день действия договора
	,last_date	date			-- последний день действия договора (м.б. не указан)
)


Написать запрос, который для данных
@first_date	date	-- начало периода
,@last_date	date	-- конец периода
,@type_id	int	-- тип договора

Вернет набор данных вида
Client_id, First_date, Last_date

Набор данных содержит все непересекающиеся и несмежные (т.е., между двумя промежутками должен быть минимум один «пустой» день) промежутки между @first_date и @last_date включительно, когда у клиента был хоть один активный договор типа @type_id. Учесть, что у клиента может быть несколько одновременно действующих однотипных договоров.

Пояснение:
Во вложенной картинке каждый прямоугольник – договор, расположенный на временной шкале, тип договора обозначен цветом.
В заданном временном промежутке нужно найти все диапазоны времени, когда действовал хотя бы один договор «синего типа». На рисунке то, что нужно вернуть обозначено как «X».

сделал такое решение, но мне кажется неверное, так как:
1) не учитываются клиенты, для каждого клиента должны быть свои непересекающиеся интервалы (спорно)
2) в данном решении идет объединение пересекающихся интервалов, думаю что пересекающихся интервалов вообще не должно быть
DECLARE
@first_date date = '2018-12-01',
@last_date date = '2018-12-31',
@type_id int = 1

select
 a.client_id, 
CASE 
		 WHEN a.first_date < @first_date 
		 THEN @first_date 	
		 ELSE a.first_date 
		END 
			AS First_date,
	  CASE 
		 WHEN b.last_date > @last_date 
		 THEN @last_date 
		 ELSE b.last_date 
		END 
			AS Last_date
from
 (select
  min(first_date) as first_date, row_number() over (order by min(first_date)) as rn, client_id, type_id
 from
  Dogovors t
 where
  not exists(select 1 from Dogovors where t.first_date > first_date and t.first_date <= dateadd(day, 1, last_date) AND t.type_id = @type_id and type_id = @type_id 
--and t.client_id = client_id
)
  AND t.type_id = @type_id
 group by
  first_date, client_id, type_id) as a 
join
 (select
  min(last_date) as last_date, row_number() over (order by min(last_date)) as rn, client_id, type_id
 from
  Dogovors t
 where
  not exists(select 1 from Dogovors where dateadd(day, 1, t.last_date) >= first_date and t.last_date < last_date AND t.type_id = @type_id and type_id = @type_id 
--and t.client_id = client_id
)
	AND t.type_id = @type_id
 group by
  last_date, client_id, type_id) as b 
on a.rn = b.rn
where 
(a.first_date >= @first_date and b.last_date <= @last_date)
or (a.first_date <= @first_date and b.last_date BETWEEN @first_date and @last_date)
or (a.first_date BETWEEN @first_date and @last_date and b.last_date >= @last_date)
or (a.first_date <= @first_date and b.last_date >= @last_date)
;


К сообщению приложен файл. Размер - 2Kb
23 янв 19, 05:44    [21791710]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
aleks222
Member

Откуда:
Сообщений: 847
Проще надо быть
with d as ( select * from Dogovors where type_id = @type_id and first_date <= @last_date and @first_date <= last_date )
  select * 
    from d 
    where not exists( select * from d as d1 where d.Client_id = d1.Client_id and d.first_date <= d1.last_date and d1.first_date <= d.last_date )
23 янв 19, 06:23    [21791718]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
Domianos
Member

Откуда:
Сообщений: 27
aleks222, спасибо
но есть одна проблемка, не могу объявить переменные до with
туплю, делаю так
DECLARE
@first_date date = '2018-12-01',
@last_date date = '2018-12-31',
@type_id int = 1;

with......


он говорит что не знает эти переменных)
23 янв 19, 06:53    [21791725]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
Domianos
Member

Откуда:
Сообщений: 27
Err] 42000 - [SQL Server]Неправильный синтаксис около ключевого слова "with".
42000 - [SQL Server]Неправильный синтаксис около ключевого слова "with". Если эта инструкция является обобщенным табличным выражением, предложением xmlnamespaces или предложением в контексте отслеживания изменений, предыдущую инструкцию необходимо завершить точкой с запятой.
42000 - [SQL Server]Необходимо объявить скалярную переменную "@type_id".
23 янв 19, 06:56    [21791726]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
Domianos
Member

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

да и кстати не работает решение на данных
INSERT INTO [Dogovors] VALUES (1, 1, '2018-12-1', '2018-12-18');
GO
INSERT INTO [Dogovors] VALUES (1, 1, '2018-12-20', '2018-12-21');
GO
INSERT INTO [Dogovors] VALUES (1, 1, '2018-12-20', '2018-12-23');
GO
INSERT INTO [Dogovors] VALUES (1, 2, '2018-1-1', '2018-7-9');
GO
INSERT INTO [Dogovors] VALUES (1, 2, '2018-5-3', '2018-8-5');
GO
INSERT INTO [Dogovors] VALUES (2, 3, '2019-1-1', '2019-1-16');
GO
INSERT INTO [Dogovors] VALUES (2, 3, '2018-12-1', '2018-12-20');
GO
23 янв 19, 09:16    [21791772]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
Sergey Sizov
Member

Откуда:
Сообщений: 1507
Domianos
aleks222,

да и кстати не работает решение на данных
INSERT INTO [Dogovors] VALUES (1, 1, '2018-12-1', '2018-12-18');
GO
INSERT INTO [Dogovors] VALUES (1, 1, '2018-12-20', '2018-12-21');
GO
INSERT INTO [Dogovors] VALUES (1, 1, '2018-12-20', '2018-12-23');
GO
INSERT INTO [Dogovors] VALUES (1, 2, '2018-1-1', '2018-7-9');
GO
INSERT INTO [Dogovors] VALUES (1, 2, '2018-5-3', '2018-8-5');
GO
INSERT INTO [Dogovors] VALUES (2, 3, '2019-1-1', '2019-1-16');
GO
INSERT INTO [Dogovors] VALUES (2, 3, '2018-12-1', '2018-12-20');
GO
А зачем столько GO? Одного последнего не хватает?
23 янв 19, 09:20    [21791776]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
Руслан Дамирович
Member

Откуда: Резиновая нерезиновая
Сообщений: 940
Domianos,

+
IF OBJECT_ID( 'tempdb..#agreements' ) IS NOT NULL
  DROP TABLE #agreements
;
CREATE TABLE #agreements (
  [client_id]   INT   NOT NULL, -- КЛИЕНТ
  [type_id]     INT   NOT NULL, -- ТИП ДОГОВОРА
  [first_date]  DATE  NOT NULL, -- ПЕРВЫЙ ДЕНЬ ДЕЙСТВИЯ ДОГОВОРА
  [last_date]   DATE            -- ПОСЛЕДНИЙ ДЕНЬ ДЕЙСТВИЯ ДОГОВОРА (М.Б. НЕ УКАЗАН)
)
;
INSERT
INTO
  #agreements
VALUES
  ( 1, 1, '20181201', '20181218'),
  ( 1, 1, '20181220', '20181221'),
  ( 1, 1, '20181220', '20181223'),
  ( 1, 2, '20180101', '20180709'),
  ( 1, 2, '20180503', '20180805'),
  ( 2, 3, '20190101', '20190116'),
  ( 2, 3, '20181201', '20181220')
;
WITH
dd0 AS (
  SELECT
    [client_id] = [client_id],
    [date]      = [first_date],
    [type]      = 0,
    [open]      = 1
  FROM
    #agreements
  UNION ALL
  SELECT
    [client_id] = [client_id],
    [date]      = ISNULL( DATEADD( DAY, 1, [last_date] ), '22000101' ),
    [type]      = 1,
    [open]      = -1
  FROM
    #agreements
),
dd1 AS (
  SELECT
    [client_id] = [client_id],
    [date]      = [date],
    [active]    = CASE WHEN SUM( [open] ) OVER ( PARTITION BY [client_id] ORDER BY [date], [type] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) > 0 THEN 1 ELSE 0 END
  FROM
    dd0
),
dd2 AS (
  SELECT
    [client_id] = dd1.[client_id],
    [date]      = ss.[date],
    [active]    = ss.[active]
  FROM
    dd1
    CROSS APPLY (
      SELECT
        [date]    = dd1.[date],
        [active]  = dd1.[active]
      UNION ALL
      SELECT
        [date]    = DATEADD( DAY, -1, dd1.[date] ),
        [active]  = 1
      WHERE
        [active] = 0
    ) ss
),
dd3 AS (
  SELECT
    [client_id] = [client_id],
    [date]      = [date],
    [active]    = [active],
    [group]     = ROW_NUMBER() OVER ( PARTITION BY [client_id] ORDER BY [date] ) 
                - ROW_NUMBER() OVER ( PARTITION BY [client_id], [active] ORDER BY [date] ) 
  FROM
    dd2
)
SELECT
  [client_id],
  [date_from] = MIN( [date] ),
  [date_till] = MAX( [date] )
FROM
  dd3
WHERE
  [active] = 1
GROUP BY
  [client_id],
  [group]
ORDER BY
  1, 2, 3
;
23 янв 19, 10:36    [21791844]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
Domianos
Member

Откуда:
Сообщений: 27
Sergey Sizov
Domianos
aleks222,

да и кстати не работает решение на данных
INSERT INTO [Dogovors] VALUES (1, 1, '2018-12-1', '2018-12-18');
GO
INSERT INTO [Dogovors] VALUES (1, 1, '2018-12-20', '2018-12-21');
GO
INSERT INTO [Dogovors] VALUES (1, 1, '2018-12-20', '2018-12-23');
GO
INSERT INTO [Dogovors] VALUES (1, 2, '2018-1-1', '2018-7-9');
GO
INSERT INTO [Dogovors] VALUES (1, 2, '2018-5-3', '2018-8-5');
GO
INSERT INTO [Dogovors] VALUES (2, 3, '2019-1-1', '2019-1-16');
GO
INSERT INTO [Dogovors] VALUES (2, 3, '2018-12-1', '2018-12-20');
GO
А зачем столько GO? Одного последнего не хватает?


это экспорт из таблицы, сам ничего не писал, видимо так мастер работает
23 янв 19, 11:04    [21791890]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
Domianos
Member

Откуда:
Сообщений: 27
Руслан Дамирович,

спасибо, интересно, надо проверить
23 янв 19, 11:05    [21791891]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
Domianos
Member

Откуда:
Сообщений: 27
Руслан Дамирович,

Сообщение 102, уровень 15, состояние 1, строка 46
Неправильный синтаксис около конструкции "ROWS".
Сообщение 102, уровень 15, состояние 1, строка 68
Неправильный синтаксис около конструкции ",".
23 янв 19, 11:33    [21791931]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
aleks222
Member

Откуда:
Сообщений: 847
Domianos
aleks222,

да и кстати не работает решение на данных
INSERT INTO [Dogovors] VALUES (1, 1, '2018-12-1', '2018-12-18');
GO
INSERT INTO [Dogovors] VALUES (1, 1, '2018-12-20', '2018-12-21');
GO
INSERT INTO [Dogovors] VALUES (1, 1, '2018-12-20', '2018-12-23');
GO
INSERT INTO [Dogovors] VALUES (1, 2, '2018-1-1', '2018-7-9');
GO
INSERT INTO [Dogovors] VALUES (1, 2, '2018-5-3', '2018-8-5');
GO
INSERT INTO [Dogovors] VALUES (2, 3, '2019-1-1', '2019-1-16');
GO
INSERT INTO [Dogovors] VALUES (2, 3, '2018-12-1', '2018-12-20');
GO


А подумать?

d
eclare @Dogovors table(
	Client_id	int 	not null 	-- клиент
	,type_id	int 	not null		-- тип договора
	,first_date	date	not null		-- первый день действия договора
	,last_date	date			-- последний день действия договора (м.б. не указан)
)

DECLARE
@first_date date = '20181201',
@last_date date = '20181231',
@type_id int = 1


INSERT INTO @Dogovors VALUES (1, 1, '2018-12-1', '2018-12-18')
, (1, 1, '2018-12-20', '2018-12-21')
, (1, 1, '2018-12-20', '2018-12-23')
, (1, 2, '2018-1-1', '2018-7-9')
, (1, 2, '2018-5-3', '2018-8-5')
, (2, 3, '2019-1-1', '2019-1-16')
, (2, 3, '2018-12-1', '2018-12-20');

select * from @Dogovors where type_id = @type_id and first_date <= @last_date and @first_date <= last_date;

with d as ( select * from @Dogovors where type_id = @type_id and first_date <= @last_date and @first_date <= last_date )
  select * 
    from d 
    where not exists( select * 
                        from d as d1 
                        where d.Client_id = d1.Client_id and d.first_date <= d1.last_date and d1.first_date <= d.last_date 
                              and not (d.first_date = d1.first_date and d1.last_date = d.last_date ) -- идентификатор строки надо иметь в таблице
                    )
;
23 янв 19, 11:45    [21791947]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
demind10
Member

Откуда:
Сообщений: 17
Domianos, мне кажется, что у Вас текст расходится с картинкой. В тексте пишете, найти непересекающиеся и несмежные промежутки, а если смотреть на картинку, то Вам надо найти непрерывные отрезки времени когда действовал хоть какой-нибудь договор нужного типа.

aleks222 похоже реализовал ваше словесное описание, а Руслан Дамирович реализовал, как мне думается. задание из картинки.

Ошибка "Неправильный синтаксис около конструкции ROWS" появляется скорее всего из-за того, что Вы используете MS SQL Server версии ниже 2012(в соседней теме вроде бы упоминался 2008), а такой синтаксис появился в 2012.

Можете попробовать мою версию решения для нахождения непрерывных отрезков времени действия договора для MS SQL SERVER 2008
(в закоментаренной части запрос для 2012 и старше):
declare @Dogovors table(
	Client_id	int 	not null 	-- клиент
	,type_id	int 	not null		-- тип договора
	,first_date	date	not null		-- первый день действия договора
	,last_date	date			-- последний день действия договора (м.б. не указан)
)

DECLARE
@first_date date = '2018-12-01',
@last_date date = '2018-12-31',
--@first_date date = '2018-12-01',
--@last_date date = '2019-01-16',
@type_id int = 1;

INSERT INTO @Dogovors VALUES (1, 1, '2018-12-1', '2018-12-18');

INSERT INTO @Dogovors VALUES (1, 1, '2018-12-20', '2018-12-21');

INSERT INTO @Dogovors VALUES (1, 1, '2018-12-20', '2018-12-23');

INSERT INTO @Dogovors VALUES (1, 2, '2018-1-1', '2018-7-9');

INSERT INTO @Dogovors VALUES (1, 2, '2018-5-3', '2018-8-5');

INSERT INTO @Dogovors VALUES (2, 3, '2019-1-1', '2019-1-16');

INSERT INTO @Dogovors VALUES (2, 3, '2018-12-1', '2018-12-20');

select * from @Dogovors where type_id = @type_id;

--select client_id, min(dt), max(dt)
--from (
--	select *, row_number() over(partition by client_id, r2 order by dt,x) as grp
--	from (
--		select *, case when r = -1 and lag(r,1,0) over(partition by client_id order by dt,x)=-1 then 500 else r end as r2
--		from (
--			select *, 
--				iif(sum(x) over(partition by client_id order by dt,x rows between unbounded preceding and current row)<0,-1,0) as r

--			from (
--				select x, Client_id, type_id, iif(x=-1,IIF(@first_date>first_date,@first_date,first_date), IIF(@last_date<last_date,@last_date, last_date)) as dt
--				from @Dogovors
--				cross join (values(-1),(1))T(x)
--				where first_date<=@last_date and last_date>=@first_date
--					and type_id = @type_id
--			) T
--		) TT
--	)TTT
--	where r2 in (-1,0)
--) TTTT
--group by client_id, grp;


----------------------------------------------------------------------------------------
with cte
as
(
	select *
		,ROW_NUMBER() over (PARTITION by client_id order by dt, x) as r
		
	from (
		select x, Client_id, type_id, 
			case when x=-1 then 
				case when @first_date>first_date then @first_date else first_date end 
			else 
				dateadd(day,1,case when @last_date<last_date then @last_date else last_date end)
			end as dt
		from @Dogovors
		cross join (values(-1),(1))T(x)
		where first_date<=@last_date and last_date>=@first_date
			and type_id = @type_id
	)T
)
select Client_id, MIN(dt) as df, dateadd(day,-1,MAX(dt)) as dt
from (
	select a.x, a.Client_id, a.type_id, a.dt,  a.r
		,row_number() over(partition by a.client_id, a.x order by sum(b.x)) as grp
	from cte a
	left join cte b on a.r>= b.r and a.Client_id = b.Client_id
	group by a.x, a.Client_id, a.type_id, a.dt,  a.r
	having not(coalesce(max(case when b.r=a.r-1 then b.x else null end),1)=-1 and case when sum(b.x)<0 then -1 else 0 end=-1)
) T
group by Client_id, grp;
23 янв 19, 14:50    [21792234]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
Domianos
Member

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

спасибо большое!
сейчас попробую
24 янв 19, 04:01    [21792767]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
Domianos
Member

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

спасибо
24 янв 19, 04:03    [21792768]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
Domianos
Member

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

для даных:
DECLARE
@first_date date = '2018-06-10',
@last_date date = '2018-06-29';

INSERT INTO [Dogovors] VALUES (1, 1, '2018-6-5', '2018-6-12');
INSERT INTO [Dogovors] VALUES (1, 1, '2018-6-13', '2018-6-13');
INSERT INTO [Dogovors] VALUES (1, 1, '2018-6-15', '2018-6-15');
INSERT INTO [Dogovors] VALUES (1, 1, '2018-6-19', '2018-6-21');
INSERT INTO [Dogovors] VALUES (1, 1, '2018-6-20', '2018-6-23');
INSERT INTO [Dogovors] VALUES (1, 1, '2018-6-25', NULL);
INSERT INTO [Dogovors] VALUES (2, 1, '2018-6-11', '2018-6-22');
INSERT INTO [Dogovors] VALUES (2, 1, '2018-6-26', '2018-6-30');
GO


результат
1	2018-06-10	2018-06-13
2	2018-06-11	2018-06-22
1	2018-06-15	2018-06-15
2	2018-06-26	2018-06-29
1	2018-06-19	2018-06-23


то есть не учитывается значение с нулевой датой на конце
INSERT INTO [Dogovors] VALUES (1, 1, '2018-6-25', NULL);


для данных
INSERT INTO [Dogovors] VALUES (1, 1, '2018-12-1', '2018-12-18');
INSERT INTO [Dogovors] VALUES (1, 1, '2018-12-20', '2018-12-21');
INSERT INTO [Dogovors] VALUES (1, 1, '2018-12-20', '2018-12-23');
INSERT INTO [Dogovors] VALUES (1, 1, '2018-1-1', '2019-1-22');
GO


результат
1	2018-12-20	2018-12-23
1	2018-12-01	2018-12-31

перекрывается
24 янв 19, 04:59    [21792775]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
Domianos
Member

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

словесное описание действительно реализовано на 100%
спасибо!
24 янв 19, 05:05    [21792776]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
Domianos
Member

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

едиственное, не учитываются null варианты в last_date

попробовал немного доработать, вот что получилось
DECLARE
@first_date date = '2018-06-10',
@last_date date = '2018-06-29',
@type_id int = 1;

with d 
as 
(   select client_id,
	first_date,
	CASE 
		WHEN last_date = null
		then @last_date
		else last_date 
		end as LastDate
	from Dogovors 
	where 
		type_id = @type_id 
		and first_date <= @last_date 
		and @first_date <= last_date 
)
select 
	client_id,
	CASE 
	 WHEN first_date < @first_date 
	 THEN @first_date 	
	 ELSE first_date 
	END AS First_date,
	CASE 
	 WHEN LastDate > @last_date 
	 THEN @last_date 
	 ELSE LastDate 
	END AS Last_date
from d 
where 
	not exists( 
				select * 
                from d as d1 
                where 
					d.Client_id = d1.Client_id 
					and d.first_date <= d1.LastDate 
					and d1.first_date <= d.LastDate 
                    and not 
						(d.first_date = d1.first_date and d1.LastDate = d.LastDate )
              )
;


но не выходит :(
24 янв 19, 05:38    [21792781]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
aleks222
Member

Откуда:
Сообщений: 847
with d0 as  ( select Client_id
                          , type_id
                          , first_date
                          , last_date = isnull(last_date, '30000101')
                      from @Dogovors 
               )
    , d as ( select *  from d0 where type_id = @type_id and first_date <= @last_date and @first_date <= last_date )
  select * 
    from d 
    where not exists( select * 
                        from d as d1 
                        where d.Client_id = d1.Client_id and d.first_date <= d1.last_date and d1.first_date <= d.last_date 
                              and not (d.first_date = d1.first_date and d1.last_date = d.last_date ) -- идентификатор строки надо иметь в таблице
                    )
;
24 янв 19, 05:49    [21792784]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
Domianos
Member

Откуда:
Сообщений: 27
походу решил

DECLARE
@first_date date = '2018-06-10',
@last_date date = '2018-06-29',
@type_id int = 1;

with d 
as 
(   select client_id,
	first_date,
	CASE 
		WHEN last_date = null
		then @last_date
		else last_date 
		end as LastDate
	from Dogovors 
	where 
		type_id = @type_id 
		and first_date <= @last_date 
		and (( last_date is null and @first_date <= @last_date )
		OR ( last_date is not null and  @first_date <= last_date))
)
select 
	client_id,
	CASE 
	 WHEN first_date < @first_date 
	 THEN @first_date 	
	 ELSE first_date 
	END AS First_date,
	LastDate
from d 
where 
	not exists( 
				select * 
                from d as d1 
                where 
					d.Client_id = d1.Client_id 
					and d.first_date <= d1.LastDate 
					and d1.first_date <= d.LastDate 
                    and not 
						(d.first_date = d1.first_date and d1.LastDate = d.LastDate )
              )
;
24 янв 19, 05:50    [21792785]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
Domianos
Member

Откуда:
Сообщений: 27
небольшая доработка в 11 строке

WHEN last_date is null
24 янв 19, 05:51    [21792787]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
Domianos
Member

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

а ларчик проще открывался :)
у меня более рабоче-крестьянская версия ;)
спасибо
24 янв 19, 05:52    [21792789]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
andrey odegov
Member

Откуда:
Сообщений: 463
Такой вариант?
WITH
  a AS (
    SELECT *,
      ROW_NUMBER() OVER (PARTITION BY client_id,type_id
                         ORDER BY first_date) AS sn
    FROM @dogovory
    WHERE (@first_date <= last_date OR last_date IS NULL) AND
          @last_date >= first_date AND @type_id = type_id
  )
SELECT
  *
FROM a
WHERE NOT EXISTS (SELECT * FROM a i
                  WHERE a.client_id = i.client_id AND a.sn != i.sn AND
                        (a.first_date <= i.last_date OR i.last_date IS NULL) AND
                        (a.last_date >= i.first_date OR a.last_date IS NULL))
;
24 янв 19, 15:47    [21793541]     Ответить | Цитировать Сообщить модератору
 Re: Найти все непересекающиеся и несмежные промежутки времени  [new]
Исраэль.
Member

Откуда:
Сообщений: 9
Если что-то не так понял, просьба не серчать.
Задача из аналит. геометрии.
Два отрезка на числ. оси А1В1 и А2В2.
Найти пересечение.

Минимум(В1, В2) - Максимум(А1,А2)

Положительное значение-пересечение.
Отрицательное-пересечения нет.
Ноль-касание.
27 янв 19, 15:36    [21795199]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить