Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Пересечение временных интервалов / 5 сообщений из 5, страница 1 из 1
21.02.2019, 18:04
    #39777481
newLoginSql
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Пересечение временных интервалов
Помогите решить оптимально задачу.

Дана некоторая сущность (ID). У этой сущности в бд хранятся две характеристики (Param1 и Param2). Храняться в разных таблицах. У каждой характеристики есть дата начала и окончания действия (dtBegin, dtEnd). Периоды не пересекаются.

Нужно выбрать из двух таблиц все временные интервалы и сочетания характеристик.

Пример:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
DECLARE @t1 TABLE ([ID] int, [Param1] varchar(100), [dtBegin] date, [dtEnd] date)

DECLARE @t2 TABLE ([ID] int, [Param2] varchar(100), [dtBegin] date, [dtEnd] date)

INSERT INTO @t1([ID], [Param1], [dtBegin], [dtEnd])
VALUES
(1, 'X', '2000-01-01', '2010-01-12'),
(1, 'Y', '2010-01-13', '9999-01-01')


INSERT INTO @t2([ID], [Param2], [dtBegin], [dtEnd])
VALUES
(1, 'W', '2000-01-01', '2008-09-05'),
(1, 'Q', '2011-09-08', '9999-01-01')



Нужен результат:
Код: sql
1.
2.
3.
4.
1, 'X', 'W', '2000-01-01', '2008-09-05'
1, 'X', NULL, '2008-09-06', '2010-01-12'
1, 'Y', NULL, '2010-01-13', '2011-09-07'
1, 'Y', 'Q', '2011-09-08', '9999-01-01'
...
Рейтинг: 0 / 0
21.02.2019, 18:07
    #39777485
newLoginSql
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Пересечение временных интервалов
Если представить всё это как две временные оси, то нужен срез по обеим. Как-то так:
...
Рейтинг: 0 / 0
21.02.2019, 19:42
    #39777567
aleks222
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Пересечение временных интервалов
newLoginSqlЕсли представить всё это как две временные оси, то нужен срез по обеим. Как-то так:

См. свою же картинку.

1. Концы всех интервалов образуют последовательность моментов времени.
2. Каждые два последовательных момента времени образуют интервал уникального сочетания характеристик.
3. Отсюда элементарный алгоритм.
...
Рейтинг: 0 / 0
22.02.2019, 05:11
    #39777676
Kopelly
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Пересечение временных интервалов
Код: 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 @t1 TABLE ([ID] int, [Param1] varchar(100), [dtBegin] date, [dtEnd] date)

DECLARE @t2 TABLE ([ID] int, [Param2] varchar(100), [dtBegin] date, [dtEnd] date)

INSERT INTO @t1([ID], [Param1], [dtBegin], [dtEnd])
VALUES
(1, 'X', '2000-01-01', '2010-01-12'),
(1, 'Y', '2010-01-13', '9999-01-01')


INSERT INTO @t2([ID], [Param2], [dtBegin], [dtEnd])
VALUES
--(1, 'W', '2000-01-01', '2008-09-05'),
--(1, 'Q', '2011-09-08', '9999-01-01');
(1, 'W', '2001-01-01', '2008-09-05'),
(1, 'Q', '2011-09-08', '2015-01-01');


with dates1 as
(Select ID,min(dtBegin) as d1_min,max(dtEnd) as d1_max  From @t1 Group by ID),
dates2 as
(Select ID,min(dtBegin) as d1_min,max(dtEnd) as d1_max  From @t2 Group by ID),
t2_nulls as (
Select * From @t2 --Исходные периоды
Union all --Добавление пустого периода в начале
Select a.ID,null as Param2, 
       a.d1_min as dtBegin,
	   dateadd(d,-1,b.d1_min) as dtEnd 
  From dates1 a
  join dates2  b on a.d1_min<b.d1_min and a.ID = b.ID
Union all --Добавление пустого периода между периодами
Select a.ID,null,
       dateadd(d,1,a.dtEnd) as dtBegin,
	   dateadd(d,-1,(Select min(b.dtBegin) From @t2 b Where a.ID = b.ID and a.dtEnd<b.dtBegin)) as dtEnd 
  From @t2 a 
 Where (Select min(b.dtBegin) From @t2 b Where a.ID = b.ID and a.dtEnd<b.dtBegin) > dateadd(d,1,a.dtEnd)
union all --Добавление пустого периода в конце
Select a.ID,null as Param2, 
       dateadd(d,-1,b.d1_max) as dtBegin,
	   a.d1_max as dtEnd 
  From dates1 a
  join dates2  b on a.d1_max>b.d1_max and a.ID = b.ID)
Select a.ID,
       a.Param1,
	   b.Param2,
	   iif(a.dtBegin>b.dtBegin,a.dtBegin,b.dtBegin) as dtBegin,
	   iif(a.dtEnd<b.dtEnd,a.dtEnd,b.dtEnd) as dtEnd  
 From @t1 a
join t2_nulls b on a.ID = b.ID and a.dtBegin<=b.dtEnd and a.dtEnd>=b.dtBegin
Order by 1,4
...
Рейтинг: 0 / 0
22.02.2019, 06:02
    #39777681
Щукина Анна
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Пересечение временных интервалов
Kopelly,

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


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