powered by simpleCommunicator - 2.0.50     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Пересечение значений по диапазонам дат
13 сообщений из 13, страница 1 из 1
Пересечение значений по диапазонам дат
    #40101650
mih.dim1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ломаю голову и не могу понять как написать запрос. Прошу помочь
Есть 2 таблицы одинаковой структуры:
create table #Main
( ID_Object int not Null,
[Begin_date] date not Null,
[End_date] date not Null,
Value float Null,
primary key(ID_Object, [Begin_date])
)

create table #Second
( ID_Object int not Null,
[Begin_date] date not Null,
[End_date] date Null,
Value float Null,
primary key(ID_Object, [Begin_date])
)

Нужна получить таблицу, где все записи из Main + заполнить недостающие диапазоны из Second.
И еще в таблице #Second - End_date может быть Null, а в #Main нет.

вот пример заполнения и результат, который должен быть.
insert into #Main
select 1, '20210305', '20210421', 1
union all
select 1, '20210601', '20210731', 2
union all
select 1, '20210801', '20210810', 3


insert into #Second
select 1, '20210101', '20210520', 10
union all
select 1, '20210521', '20210715', 20
union all
select 1, '20210801', '20211231', 30

insert into #Result
select 1, '20210101', '20210304', 10
union all
select 1, '20210305', '20210421', 1
union all
select 1, '20210422', '20210520', 10
union all
select 1, '20210521', '20210530', 20
union all
select 1, '20210601', '20210731', 2
union all
select 1, '20210801', '20210810', 3
union all
select 1, '20210811', '20211231', 30
...
Рейтинг: 0 / 0
Пересечение значений по диапазонам дат
    #40101651
mih.dim1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Забыл добавить что в таблицах может быть много записей (миллионы)
...
Рейтинг: 0 / 0
Пересечение значений по диапазонам дат
    #40101667
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1. Находишь дырки в #Main.
2. Заполняешь их из #Second.

Если у тя гарантировано "отсутствие перекрытия диапазонов" в каждой из табличек - ничего особо сложного.
...
Рейтинг: 0 / 0
Пересечение значений по диапазонам дат
    #40101799
mih.dim1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
aleks222,

Я же пример привел. Пересекаться могут как угодно две таблицы по датам.
...
Рейтинг: 0 / 0
Пересечение значений по диапазонам дат
    #40101804
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да пусть пересекаются. Это-то тут при чём? Вроде Алекс вполне вменяемо алгоритм расписал... а пересечения он имел в виду в пределах одной таблицы, а не двух вместе.
...
Рейтинг: 0 / 0
Пересечение значений по диапазонам дат
    #40101898
mih.dim1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Akina
Да пусть пересекаются. Это-то тут при чём? Вроде Алекс вполне вменяемо алгоритм расписал... а пересечения он имел в виду в пределах одной таблицы, а не двух вместе.


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

Логику я понимаю, но как сделать такой запрос - не пойму.
...
Рейтинг: 0 / 0
Пересечение значений по диапазонам дат
    #40101917
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mih.dim1
Akina
Да пусть пересекаются. Это-то тут при чём? Вроде Алекс вполне вменяемо алгоритм расписал... а пересечения он имел в виду в пределах одной таблицы, а не двух вместе.


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

Логику я понимаю, но как сделать такой запрос - не пойму.


Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
declare @Main table 
( ID_Object int not Null,
[Begin_date] date not Null,
[End_date] date not Null,
Value float Null,
primary key(ID_Object, [Begin_date])
)

insert into @Main
select 1, '20210305', '20210421', 1
union all
select 1, '20210601', '20210731', 2
union all
select 1, '20210801', '20210810', 3
;
with m as ( select * from @Main )
   , b as ( select ID_Object, Begin_date = m.End_date, n = row_number() over(partition by ID_Object order by End_date) from m where not exists( select * from m as t where t.ID_Object = m.ID_Object and m.End_date = t.Begin_date ) )
   , e as ( select ID_Object, End_date = m.Begin_date, n = row_number() over(partition by ID_Object order by Begin_date) from m where not exists( select * from m as t where t.ID_Object = m.ID_Object and m.Begin_date = t.End_date ) )
   select ID_Object = isnull(b.ID_Object, e.ID_Object), Begin_date = isnull(Begin_date, '10000101'), End_date = isnull(End_date, '30000101') from b full outer join e on b.ID_Object = e.ID_Object and b.n = e.n - 1
     order by ID_Object, Begin_date
...
Рейтинг: 0 / 0
Пересечение значений по диапазонам дат
    #40103408
mih.dim1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
aleks222,
вот какой запрос получился в итоге, может кому то полезно будет

;WITH C AS
(
SELECT [End_date] AS [Start_Date], LEAD([Begin_date],1,'99991231') OVER(ORDER BY [Begin_date]) AS Stop_date
FROM @Main
union all
select '19000101' [Start_Date], min([Begin_date]) AS Stop_date
from @Main
)

select S.ID_Object,
utils.MaxDate(V.[Start_Date],S.Begin_Date) Begin_Date,
utils.MinDate(V.[Stop_Date],S.End_Date) End_Date,
S.Value
from @Second S
inner join (
SELECT DATEADD(day, 1, [Start_Date]) AS [Start_Date], DATEADD(day, -1, Stop_date) Stop_date
FROM C
WHERE DATEDIFF(day, [Start_Date], Stop_date) > 1
) V on dbo.Is_Intervals_Cross(V.Start_Date,V.Stop_date, S.Begin_date, S.End_date)=1
union all
select ID_Object, Begin_Date, End_Date, Value
from @Main
order by 2
...
Рейтинг: 0 / 0
Пересечение значений по диапазонам дат
    #40103409
mih.dim1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сначала нашел пустые промежутки, а потом пересечение с ними заполнил из второй таблице.
...
Рейтинг: 0 / 0
Пересечение значений по диапазонам дат
    #40103410
Ролг Хупин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mih.dim1
Сначала нашел пустые промежутки, а потом пересечение с ними заполнил из второй таблице .



"Что ж такое, были же люди как люди, и вдруг все сразу стали кретины. Парадокс." (ц, Брат-2)
...
Рейтинг: 0 / 0
Пересечение значений по диапазонам дат
    #40103431
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mih.dim1
aleks222,
вот какой запрос получился в итоге, может кому то полезно будет

;WITH C AS
(
SELECT [End_date] AS [Start_Date], LEAD([Begin_date],1,'99991231') OVER(ORDER BY [Begin_date]) AS Stop_date
FROM @Main
union all
select '19000101' [Start_Date], min([Begin_date]) AS Stop_date
from @Main
)

select S.ID_Object,
utils.MaxDate(V.[Start_Date],S.Begin_Date) Begin_Date,
utils.MinDate(V.[Stop_Date],S.End_Date) End_Date,
S.Value
from @Second S
inner join (
SELECT DATEADD(day, 1, [Start_Date]) AS [Start_Date], DATEADD(day, -1, Stop_date) Stop_date
FROM C
WHERE DATEDIFF(day, [Start_Date], Stop_date) > 1
) V on dbo.Is_Intervals_Cross(V.Start_Date,V.Stop_date, S.Begin_date, S.End_date)=1
union all
select ID_Object, Begin_Date, End_Date, Value
from @Main
order by 2

Извини, дарагой.
Это может быть полезно только как пример дурного кода.
...
Рейтинг: 0 / 0
Пересечение значений по диапазонам дат
    #40103471
mih.dim1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
aleks222
mih.dim1
aleks222,
вот какой запрос получился в итоге, может кому то полезно будет

;WITH C AS
(
SELECT [End_date] AS [Start_Date], LEAD([Begin_date],1,'99991231') OVER(ORDER BY [Begin_date]) AS Stop_date
FROM @Main
union all
select '19000101' [Start_Date], min([Begin_date]) AS Stop_date
from @Main
)

select S.ID_Object,
utils.MaxDate(V.[Start_Date],S.Begin_Date) Begin_Date,
utils.MinDate(V.[Stop_Date],S.End_Date) End_Date,
S.Value
from @Second S
inner join (
SELECT DATEADD(day, 1, [Start_Date]) AS [Start_Date], DATEADD(day, -1, Stop_date) Stop_date
FROM C
WHERE DATEDIFF(day, [Start_Date], Stop_date) > 1
) V on dbo.Is_Intervals_Cross(V.Start_Date,V.Stop_date, S.Begin_date, S.End_date)=1
union all
select ID_Object, Begin_Date, End_Date, Value
from @Main
order by 2

Извини, дарагой.
Это может быть полезно только как пример дурного кода.


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



"Что ж такое, были же люди как люди, и вдруг все сразу стали кретины. Парадокс." (ц, Брат-2)


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


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