powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Найти все непересекающиеся и несмежные промежутки времени
23 сообщений из 23, страница 1 из 1
Найти все непересекающиеся и несмежные промежутки времени
    #39763175
Domianos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дана таблица
Код: sql
1.
2.
3.
4.
5.
6.
Dogovors(
	Client_id	int 	not null 	-- клиент
	,type_id	int 	not null		-- тип договора
	,first_date	date	not null		-- первый день действия договора
	,last_date	date			-- последний день действия договора (м.б. не указан)
)



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


Вернет набор данных вида
Код: sql
1.
Client_id, First_date, Last_date


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

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

сделал такое решение, но мне кажется неверное, так как:
1) не учитываются клиенты, для каждого клиента должны быть свои непересекающиеся интервалы (спорно)
2) в данном решении идет объединение пересекающихся интервалов, думаю что пересекающихся интервалов вообще не должно быть
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
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)
;
...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39763180
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Проще надо быть
Код: sql
1.
2.
3.
4.
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 )
...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39763185
Domianos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
aleks222, спасибо
но есть одна проблемка, не могу объявить переменные до with
туплю, делаю так
Код: sql
1.
2.
3.
4.
5.
6.
DECLARE
@first_date date = '2018-12-01',
@last_date date = '2018-12-31',
@type_id int = 1;

with......



он говорит что не знает эти переменных)
...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39763186
Domianos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: sql
1.
2.
3.
Err] 42000 - [SQL Server]Неправильный синтаксис около ключевого слова "with".
42000 - [SQL Server]Неправильный синтаксис около ключевого слова "with". Если эта инструкция является обобщенным табличным выражением, предложением xmlnamespaces или предложением в контексте отслеживания изменений, предыдущую инструкцию необходимо завершить точкой с запятой.
42000 - [SQL Server]Необходимо объявить скалярную переменную "@type_id".
...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39763217
Domianos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
aleks222,

да и кстати не работает решение на данных
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
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
...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39763221
Sergey Sizov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Domianosaleks222,

да и кстати не работает решение на данных
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
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? Одного последнего не хватает?
...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39763265
Руслан Дамирович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Domianos,

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
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
;

...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39763290
Domianos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Sergey SizovDomianosaleks222,

да и кстати не работает решение на данных
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
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? Одного последнего не хватает?

это экспорт из таблицы, сам ничего не писал, видимо так мастер работает
...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39763291
Domianos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Руслан Дамирович,

спасибо, интересно, надо проверить
...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39763319
Domianos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Руслан Дамирович,

Код: sql
1.
2.
3.
4.
Сообщение 102, уровень 15, состояние 1, строка 46
Неправильный синтаксис около конструкции "ROWS".
Сообщение 102, уровень 15, состояние 1, строка 68
Неправильный синтаксис около конструкции ",".
...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39763329
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Domianosaleks222,

да и кстати не работает решение на данных
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
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
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
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 ) -- идентификатор строки надо иметь в таблице
                    )
;
...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39763527
demind10
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Domianos, мне кажется, что у Вас текст расходится с картинкой. В тексте пишете, найти непересекающиеся и несмежные промежутки, а если смотреть на картинку, то Вам надо найти непрерывные отрезки времени когда действовал хоть какой-нибудь договор нужного типа.

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

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

Можете попробовать мою версию решения для нахождения непрерывных отрезков времени действия договора для MS SQL SERVER 2008
(в закоментаренной части запрос для 2012 и старше):
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
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;
...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39763895
Domianos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
demind10,

спасибо большое!
сейчас попробую
...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39763896
Domianos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
aleks222,

спасибо
...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39763901
Domianos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
demind10,

для даных:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
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



результат
Код: sql
1.
2.
3.
4.
5.
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



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



для данных
Код: sql
1.
2.
3.
4.
5.
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



результат
Код: sql
1.
2.
1	2018-12-20	2018-12-23
1	2018-12-01	2018-12-31


перекрывается
...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39763902
Domianos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
aleks222,

словесное описание действительно реализовано на 100%
спасибо!
...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39763906
Domianos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
aleks222,

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

попробовал немного доработать, вот что получилось
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
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 )
              )
;



но не выходит :(
...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39763908
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
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 ) -- идентификатор строки надо иметь в таблице
                    )
;
...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39763909
Domianos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
походу решил

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
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 )
              )
;
...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39763910
Domianos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
небольшая доработка в 11 строке

Код: sql
1.
WHEN last_date is null
...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39763912
Domianos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
aleks222,

а ларчик проще открывался :)
у меня более рабоче-крестьянская версия ;)
спасибо
...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39764456
andrey odegov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Такой вариант ?
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
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))
;
...
Рейтинг: 0 / 0
Найти все непересекающиеся и несмежные промежутки времени
    #39765495
Исраэль.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если что-то не так понял, просьба не серчать.
Задача из аналит. геометрии.
Два отрезка на числ. оси А1В1 и А2В2.
Найти пересечение.

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

Положительное значение-пересечение.
Отрицательное-пересечения нет.
Ноль-касание.
...
Рейтинг: 0 / 0
23 сообщений из 23, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Найти все непересекающиеся и несмежные промежутки времени
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]