|
Нужен алгоритм расчета вытеснения периодов | ☑ | ||
---|---|---|---|---|
0
Gorr
07.02.19
✎
11:32
|
Коллеги день добрый,
Прошу поделиться опытом. Нужен алгоритм расчета вытеснения периодов. На входе имеем список периодов с разными приоритетами и интервал времени. На выходе необходимо получить список непересекающихся периодов в заданном диапазоне дат с учетом их приоритетов. Аналог получения Фактического периода действия записей регистра расчета. В идеале запросом. Быть может кто-нибудь сталкивался??? |
|||
1
Garykom
гуру
07.02.19
✎
14:32
|
Сколько платишь?
|
|||
2
Cyberhawk
07.02.19
✎
14:33
|
Зачем запросом? Хочешь быть незаменимым Васей? ))
|
|||
3
Gorr
08.02.19
✎
11:23
|
Добрый день, коллеги. Уже нашел как сделать запросом. Кому интересно суть - сначала создается временная таблица дат с каждой датой из интервала. Можно через генерацию числовой последовательности. Далее соединяем ее с исходной таблицей периодов по дате_периода между датой начала и датой окончания из исходной таблицы периодов. Таким образом получим таблицу со всеми периодами на каждую дату из интервала. Группировкой по дате определяем период с максимальным приоритетом на каждую дату интервала.
В итоге получим таблицу с каждой уникальной датой интервала и соответствующий этой дате период с максимальным приоритетом. Нормализация периодов запросом. Объединением таблицы с самой собой разбиваем ее на временные таблицу начал периодов и таблицу окончаний периодов. Соединением последних двух таблиц получаем результат. Здесь немного сложнее для понимания, но легко реализуется и пост обработкой результата запроса. (2) на мой взгляд, запросом всегда красивее. и правильнее. |
|||
4
Garykom
гуру
08.02.19
✎
11:38
|
(3) >на мой взгляд, запросом всегда красивее. и правильнее.
Заранее проверь что будет с твоим "запросом" при очень большом количестве периодов. Ну скажем если их тысячи и больше. |
|||
5
Gorr
08.02.19
✎
12:12
|
Специфика задачи такова, что периоды представлены видами расчетов сотрудника, а интервал год.
Нормально там все) |
|||
6
Cyberhawk
08.02.19
✎
19:23
|
(3) "запросом всегда красивее. и правильнее" // Смотря что считается критерием правильности. Иногда красотой жертвуют ради повышения понятности кода и, как следствие, сопровождаемости оного.
|
|||
7
Krendel
08.02.19
✎
19:27
|
А что не сделать регистр сведений в котором считать пригритетность, а запросом просто собирать результат
|
|||
8
Cyberhawk
08.02.19
✎
20:21
|
(7) Тебя разработчики ЗУП 3 покусали?
|
|||
9
Nyoko
08.02.19
✎
20:45
|
в бит финансе подобное видал, но там рекурсия была .
|
|||
10
Рэйв
08.02.19
✎
20:46
|
(0)Помню свой вынос мозга в решении этой задачи на час примерно.
Не продам и не скажу.Это святое:-) |
|||
11
Garykom
гуру
08.02.19
✎
22:19
|
Хз как запросом но кодом:
1. Делаем ТЗ всех дат (начала и конца) в одну колонку, не забываем добавить даты начала и конца интервала, сортируем по возрастанию. 2. Перебираем и пишем в новую ТЗ все интервалы 1-2, 2-3, 3-4, 4-5 и т.д., нумеруем их. 3. Перебираем все начальные периоды в порядке снижения приоритета и каждому забираем интервалы из которых он состоит (сравнение дат на > и <), если интервала не досталось (при заборе удаляем его откуда забрали) то он в пролете. Если в пролете вернуть интервалы назад в кучу. Если все интервалы подобрали (сумма подобранных = длине периода) то в результат. 4. Получаем нужный результат, алгоритм работает очень шустро, сложность примерно N*N. |
|||
12
Krendel
09.02.19
✎
04:17
|
(8) я же не программер, да и чем сложнее постановка, тем дольше сдавать ;-)
|
|||
13
Конструктор1С
09.02.19
✎
05:46
|
Лишь бы в запрос всё пихать. Задача решается за один проход
Функция ВыделитьНепересекающиесяПериоды(Знач ТаблицаПериодов) Если ТаблицаПериодов.Количество() <= 1 Тогда Возврат ТаблицаПериодов; КонецЕсли; ТаблицаНепересекающихсяПериодов = Новый ТаблицаЗначений; ТаблицаНепересекающихсяПериодов.Колонки.Добавить("ДатаНачала", Новый ОписаниеТипов("Дата")); ТаблицаНепересекающихсяПериодов.Колонки.Добавить("ДатаОкончания", Новый ОписаниеТипов("Дата")); ТаблицаПериодов.Сортировать("ДатаНачала, ДатаОкончания"); ДатаНачала = ТаблицаПериодов[0].ДатаНачала; ДатаОкончания = ТаблицаПериодов[0].ДатаОкончания; Для Индекс = 1 По ТаблицаПериодов.Количество() - 1 Цикл СтрокаПериода = ТаблицаПериодов[Индекс]; Если СтрокаПериода.ДатаНачала > ДатаОкончания Тогда НоваяСтрока = ТаблицаНепересекающихсяПериодов.Добавить(); НоваяСтрока.ДатаНачала = ДатаНачала; НоваяСтрока.ДатаОкончания = ДатаОкончания; ДатаНачала = СтрокаПериода.ДатаНачала; ДатаОкончания = СтрокаПериода.ДатаОкончания; Иначе ДатаНачала = Макс(ДатаНачала, СтрокаПериода.ДатаНачала); ДатаОкончания = Мин(ДатаОкончания, СтрокаПериода.ДатаОкончания); КонецЕсли; КонецЦикла; // Последний период НоваяСтрока = ТаблицаНепересекающихсяПериодов.Добавить(); НоваяСтрока.ДатаНачала = ДатаНачала; НоваяСтрока.ДатаОкончания = ДатаОкончания; Возврат ТаблицаНепересекающихсяПериодов; КонецФункции // ВыделитьНепересекающиесяПериоды() |
|||
14
Конструктор1С
09.02.19
✎
05:51
|
(3) "на мой взгляд, запросом всегда красивее. и правильнее"
Ага, потом сидишь над этим "хитрым" запросом и гадаешь, чего же там такое автор пытался изобразить. А "ёмкие" имена временных таблиц, типа "ВТ1", "ВТ2", "Таблица", "ИтогТабл" и т.п., очень помогают разобраться в запросе. Запрос не панацея, его нужно использовать где он уместен |
|||
15
Конструктор1С
09.02.19
✎
06:14
|
(13) функция получилась излишне громоздкой, каюсь
Функция ВыделитьНепересекающиесяПериоды(Знач ТаблицаПериодов) Если ТаблицаПериодов.Количество() <= 1 Тогда Возврат ТаблицаПериодов; КонецЕсли; ТаблицаНепересекающихсяПериодов = ТаблицаПериодов.СкопироватьКолонки("ДатаНачала, ДатаОкончания"); ТаблицаПериодов.Сортировать("ДатаНачала, ДатаОкончания"); ДатаНачала = ТаблицаПериодов[0].ДатаНачала; ДатаОкончания = ТаблицаПериодов[0].ДатаОкончания; Для Индекс = 1 По ТаблицаПериодов.Количество() - 1 Цикл СтрокаПериода = ТаблицаПериодов[Индекс]; Если СтрокаПериода.ДатаНачала > ДатаОкончания Тогда ДобавитьНовуюСтрокуПериода(ТаблицаНепересекающихсяПериодов, ДатаНачала, ДатаОкончания); ДатаНачала = СтрокаПериода.ДатаНачала; ДатаОкончания = СтрокаПериода.ДатаОкончания; Иначе ДатаНачала = Макс(ДатаНачала, СтрокаПериода.ДатаНачала); ДатаОкончания = Мин(ДатаОкончания, СтрокаПериода.ДатаОкончания); КонецЕсли; КонецЦикла; // Последний период ДобавитьНовуюСтрокуПериода(ТаблицаНепересекающихсяПериодов, ДатаНачала, ДатаОкончания); Возврат ТаблицаНепересекающихсяПериодов; КонецФункции // ВыделитьНепересекающиесяПериоды() Процедура ДобавитьНовуюСтрокуПериода(Таблица, ДатаНачала, ДатаОкончания) НоваяСтрока = Таблица.Добавить(); НоваяСтрока.ДатаНачала = ДатаНачала; НоваяСтрока.ДатаОкончания = ДатаОкончания; КонецПроцедуры |
|||
16
Конструктор1С
09.02.19
✎
06:38
|
А, стоп, нужны ведь непересекающиеся, у меня получаются наоборот перекрытия
|
|||
17
SleepyHead
гуру
09.02.19
✎
07:57
|
(0) Я на 77 на одной самописке такое делал на таблицах значений. Работало охренительно долго, но зато результат был проверяемый и понятный.
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |