gifts2017

Расчет рабочих дней в запросе

Опубликовал Max (fotov) в раздел Программирование - Практика программирования

Популярная тема - расчет просрочки в рабочих днях. Если это нужно сделать по одному объекту, то тут всё достаточно просто. Что же делать, если нужно сразу по множеству объектов, при этом быстро и не особо загружая сервер?

Исходные данные

Есть регистр сведений с данными по регламентированному производственному календарю "РегламентированныйПроизводственныйКалендарь". Измерение ДатаКалендаря и ресурс Рабочий типа булево, обозначающий рабочий день.

Для того, чтобы получить в запросе разницу в рабочих днях, я предлагаю создавать вспомогательную таблицу вида ДатаКалендаря, НомерРабочегоДня. Соответственно для расчета просрочки просто делается соединение вспомогательной таблицы и получаются номера рабочего дня, и разница получается простым вычитанием.

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

 

ВЫБРАТЬ РАЗРЕШЕННЫЕ
	РегламентированныйПроизводственныйКалендарь.ДатаКалендаря КАК ДатаКалендаря
ПОМЕСТИТЬ ВТ_ДанныеКалендаря
ИЗ
	РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь
ГДЕ
	(РегламентированныйПроизводственныйКалендарь.Рабочий = ИСТИНА)
	И ГОД(РегламентированныйПроизводственныйКалендарь.ДатаКалендаря) >= ГОД(&ТекущаяДата) - 1
	И ГОД(РегламентированныйПроизводственныйКалендарь.ДатаКалендаря) <= ГОД(&ТекущаяДата) + 1

ИНДЕКСИРОВАТЬ ПО
	ДатаКалендаря
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ РАЗРЕШЕННЫЕ
	ВТ_ДанныеКалендаря.ДатаКалендаря КАК ДатаКалендаря,
	СУММА(1) КАК НомерРабочегоДня
ПОМЕСТИТЬ ВТ_НомераРабочихДней
ИЗ
	ВТ_ДанныеКалендаря КАК ВТ_ДанныеКалендаря
		ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ДанныеКалендаря КАК ВТ_ДанныеКалендаряДляСуммы
		ПО ВТ_ДанныеКалендаря.ДатаКалендаря >= ВТ_ДанныеКалендаряДляСуммы.ДатаКалендаря

СГРУППИРОВАТЬ ПО
	ВТ_ДанныеКалендаря.ДатаКалендаря

ИНДЕКСИРОВАТЬ ПО
	ДатаКалендаря



См. также

Подписаться Добавить вознаграждение

Комментарии

1. ZLENKO.PRO (ZLENKO) 25.12.14 15:58
Вот в этом отчете по просроченной дебиторке используется расчет по рабочим дням http://infostart.ru/public/117647/

2. Марина Чирина (chmv) 25.12.14 16:52
Любопытно. А как на счет соединения в запросе даты+наименование
Например ФизЛицо.Наименование+ФизЛицо.Дата
3. Сергей (ildarovich) 26.12.14 00:34
А в чем проблема просто соединить таблицу долгов с "РегистрСведений.РегламентированныйПроизводственныйКалендарь" по условию ДатаКалендаря МЕЖДУ ДатаВозникновенияДолга И &ТекущаяДата ГДЕ Рабочий = ИСТИНА и получить число рабочих дней как КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ДатаКалендаря) ? По идее, при соединении должен использоваться индекс и никаких проблем с производительностью у этого запроса быть не должно.
А вот в предлагаемом решении проблемы есть - время предварительного расчета таблицы "интеграл рабочих дней" квадратично зависит от интервала. Не зря тут ограничение на плюс-минус год стоит. И что будет, если долг имеет двухгодичную давность?
В общем, для убедительности нужно привести проблемный запрос, который вы пытаетесь таким образом оптимизировать и сравнительные замеры времени выполнения запросов. Иначе может оказаться, что предлагается никому не нужное усложнение простого запроса.
Muhin555; xzorkiix; Badakismati; Valerich; +4 Ответить 1
4. Станислав Копылов (ksuman) 31.12.14 14:01
(3) ildarovich, Вы правильно заметили: ГОД(РегламентированныйПроизводственныйКалендарь.ДатаКалендаря) в условиях - и сервер БД не будет использовать Кластерный индекс по полю даты календаря, что в случае использования системы после десятка лет неоправданно увеличит время выполнения запроса.

Можно использовать Пакетный запрос, только условие надо писать корректно: не так как нам читабельно, а так чтобы быстро выполнялся.
xzorkiix; +1 Ответить
5. Сергей Носков (Sergey.Noskov) 13.01.15 13:14
Мы таким же запросом определяли, потом таки переделали регистр - добавили несколько ресурсов, соответствующих самым часто востребованным рабочим дням (след рабочий день, третий, 10й)
6. Дмитрий Егоров (Diego_Iv) 15.01.15 10:19
Мы тоже поначалу использовали аналогичный запрос в отчетах по просроченной задолженности.
На тысяче контрагентов (у контрагента может быть до 10 договоров с разными условиями по срокам оплаты, сроки считаются как по календарным, так и рабочим дням) отчет мог строиться до 30 минут, из-за того что срок погашения долга рассчитывался в момент формирования отчета для каждого документа, сформировавшего этот долг).
В результате сделали так: добавили регистр сведений "сроки погашения". Измерения - Договор контрагента, документ расчетов. Ресурс - Дата погашения.
В момент проведения документа поступления (реализации) подпиской на событие в регистр добавляется запись с уже рассчитанной датой погашения долга по этому документу.

В результате все отчеты по долгам строятся за секунды.
dgolovanov; +1 Ответить
7. Марина Чирина (chmv) 16.01.15 12:09
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа