Запросом выделить пересечения интервалов времени в отдельные интервалы #798956


#0 by PCcomCat
Доброго времени! Прошу помощи. Возможно ли ЗАПРОСОМ объединить интервалы с разбивкой при пересечении? Есть режим работы: С учетом целых суток запросом получаю первые интервалы: 00:00 - 08:00 - нераб. время Есть вторые интервалы, в которые выполняются работы: 09:00 - 11:00 - 1-я работа Нужно объединить интервалы так, чтобы учесть их пересечение и выделить отдельным интервалом. В результате нужно получить: 00:00 - 08:00 - нераб. время 08:00 - 09:00 - раб. время 09:00 - 11:00 - раб. время (это 1-я работа) 11:00 - 12:00 - раб. время 12:00 - 13:00 - нераб. время (это 2-я работа) 13:00 - 16:00 - раб. время (это 2-я работа) 13:00 - 17:00 - раб. время Поделитесь опытом, если такое выполняли. Заранее благодарю.
#1 by Cyberhawk
#2 by PCcomCat
? ))
#3 by Cyberhawk
Позови его в ветку
#4 by PCcomCat
Ildarovich ! ))
#5 by cw014
Порядок сначала по первой дате, потом по второй
#6 by PCcomCat
Есть, конечно, мысля вытащить интервалы без пересечений и интервалы с пересечением, затем интервалы с пересечением разделить на три таблицы: левое пересечение, внутреннее пересечение, правое пересечение. Но может есть проще вариант?! А я не догоняю...
#7 by cw014
я тебе в уже идею дал
#8 by PCcomCat
Для меня она туманна... :(
#9 by cw014
Выбирай все периоды в запросе объединением. У тебя два поля "Время начала" и "Время окончания". Делай упорядочивание сначала по "Время начала" потом по "Время окончания"
#10 by PCcomCat
Сейчас у меня две разные таблицы. Я так понимаю, нужно слить их в одну? Думаю......
#11 by Ildarovich
Вот одно из возможных решений. Его суть - в условии пересечения отрезков для соединения таблиц
#12 by PCcomCat
Спасибо большое!!! Правда теряю три интервала при таком соединении: 08:00 - 09:00 Мне почти удалось собрать методом в - рюшечки остались. Но вашим методом красивее и проще. Потерянное добавлю самостоятельно. Еще раз спасибо!!!!
#13 by PCcomCat
В я могу получить интервалы пересечений и не участвовавшие в анализе пересечений интервалы. Но всё-равно придется вытаскивать левый и правый интервалы не вошедшие в пересечение, но участвовавшие в анализе.
#14 by PCcomCat
Окончательный вариант выложу.
#15 by PCcomCat
У меня получилось вот так самостоятельно дернуть интервалы:     И НЕ ВЫБОР Так получаю пересечения и левые интервалы от пересечений. С правым вожусь. Если в "пересечении" поставить левое соединение, то получаю то же, что и в   - вот тут я затупила((.
#16 by Ildarovich
Понял, что в задаче также требуется найти незанятые никакими работами интервалы. Если двигаться в том же направлении, что и , то достаточно изменить две вещи: 1) добавить во вторую таблицу пустые промежутки: 2) Упростить сам запрос, сделав соединение внутренним, поскольку пересечение после дополнения 1) будет всегда: Правда, тут "некрасивая" часть, связанная с определением интервалов дополнения (интервалов между интервалами), оставлена за скобками. Для определения интервалов дополнения их потребуется объединить с интервалами (0, 0), (23:59:59, 23:59:59), соединить эту таблицу с собой по неравенству, сгруппировать, найти интервалы (макс(слева), от)  - получается довольно длинно, да еще повторить для первой и второй таблицы.
#17 by Ildarovich
+ допустил две неточности: в 1) "2-я работа" заменить на "без работы", в 2) ЛЕВОЕ СОЕДИНЕНИЕ заменить на ВНУТРЕННЕЕ СОЕДИНЕНИЕ
#18 by PCcomCat
Спасибо! Попробую разобраться. Пока пошла понятным путем: объединением с левыми и правыми интервалами.
#19 by PCcomCat
Плюс ко всему, приходится учитывать, что пересечение концов может совпадать, и при этом начало следующего интервала - это конец предыдущего, причем секунда в секунду. Например: график работы 13:00 - 17:00 сами работы могут иметь интервалы: 09:00 - 12:00 12:00 - 16:00. Мысль понятна. Также для себя приятно, что двигаюсь в нужном направлении.
#20 by eryomin
ВЫБРАТЬ     13,     17 ; ОБЪЕДИНИТЬ ВЫБРАТЬ     0,     ЛОЖЬ ИЗ     ЛОЖЬ ИЗ ВЫБРАТЬ     ЛОЖЬ ИЗ ГДЕ     ВТ_12.Начало ЕСТЬ NULL ; ОБЪЕДИНИТЬ ВЫБРАТЬ     0,     ЛОЖЬ ИЗ     ЛОЖЬ ИЗ ВЫБРАТЬ     ЛОЖЬ ИЗ ГДЕ     ВТ_22.Начало ЕСТЬ NULL ; ГДЕ     ВТ_2.Начало ЕСТЬ NULL ОБЪЕДИНИТЬ ВЫБРАТЬ ВЫБРАТЬ ГДЕ     ВТ_1.Начало ЕСТЬ NULL ОБЪЕДИНИТЬ ВЫБРАТЬ
#21 by PCcomCat
В общем, я как упёртая или упоротая, пошла путем вычисления левых и правых интервалов. Окончательный рабочий код для вышеуказанного примера:         КОГДА ИнтервалыРабот.Работа ЕСТЬ NULL     От Не исключаю, конечно, косяки. Их уже буду проверять на реальных данных - в бою, так сказать. Еще раз выражаю благодарность  Ildarovich  ! Лично я не додумалась, например, до этого ЕСТЬNULL(ИнтервалыРабот.До, ДАТАВРЕМЯ(1, 1, 2!)).
#22 by eryomin
Никак не могу побороть форматирование: ВЫБРАТЬ     13,     17 ; ОБЪЕДИНИТЬ ВЫБРАТЬ     0,     ЛОЖЬ ИЗ     ЛОЖЬ ИЗ ВЫБРАТЬ     ЛОЖЬ ИЗ ГДЕ     ВТ_12.Начало ЕСТЬ NULL ; ОБЪЕДИНИТЬ ВЫБРАТЬ     0,     ЛОЖЬ ИЗ     ЛОЖЬ ИЗ ВЫБРАТЬ     ЛОЖЬ ИЗ ГДЕ     ВТ_22.Начало ЕСТЬ NULL ; ГДЕ     ВТ_2.Начало ЕСТЬ NULL ОБЪЕДИНИТЬ ВЫБРАТЬ ВЫБРАТЬ ГДЕ     ВТ_1.Начало ЕСТЬ NULL ОБЪЕДИНИТЬ ВЫБРАТЬ
#23 by PCcomCat
Да, результат тот же, объединений больше)). Только если я добавлю еще интервал работ 9-11, то некоторые отрезки задваиваются. Тоже спасибо!
#24 by Ildarovich
Осталась некоторая неудовлетворенность приведенными решениями этой задачи. Поэтому добавлю полное решение, которое кажется более простым:Принцип решения в том, чтобы все моменты времени (все начала, концы интервалов, 0, 24) собрать без повторений в одну таблицу, затем по этой таблице построить все самые мелкие интервалы, а к ним уже присоединять включающие их интервалы работ, рабочего времени и тому подобное. Такой принцип будет работать и для больше чем двух таблиц пересекающихся интервалов. Проблема этого и всех приведенных запросов в том, что они будут сильно терять производительность при росте количества интервалов (если их станет больше нескольких тысяч). С этим можно справится, применяя прием из статьи для определения интервалов и прием из статьи (или его упрощенную версию) для определения пересечения интервалов.
Тэги: 1С 8
Ответить:
Комментарии доступны только авторизированным пользователям

В этой группе 1С