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

Откуда:
Сообщений: 10
Помогите решить оптимально задачу.

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

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

Пример:
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, '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'
21 фев 19, 18:04    [21816698]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение временных интервалов  [new]
newLoginSql
Member

Откуда:
Сообщений: 10
Если представить всё это как две временные оси, то нужен срез по обеим. Как-то так:

К сообщению приложен файл. Размер - 15Kb
21 фев 19, 18:07    [21816704]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение временных интервалов  [new]
aleks222
Member

Откуда:
Сообщений: 855
newLoginSql
Если представить всё это как две временные оси, то нужен срез по обеим. Как-то так:


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

1. Концы всех интервалов образуют последовательность моментов времени.
2. Каждые два последовательных момента времени образуют интервал уникального сочетания характеристик.
3. Отсюда элементарный алгоритм.
21 фев 19, 19:42    [21816809]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение временных интервалов  [new]
Kopelly
Member

Откуда: Красноярск
Сообщений: 289
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
22 фев 19, 05:11    [21816960]     Ответить | Цитировать Сообщить модератору
 Re: Пересечение временных интервалов  [new]
Щукина Анна
Member

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

Как всё сложно-то....
А всего-то надо было - развернуть интервалы в последовательность точек, после чего - свернуть полученные точки в новые интервалы. Собственно, об этом и написал Alex222
22 фев 19, 06:02    [21816965]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить