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

25.12.14

Разработка - Запросы

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

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

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

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

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

 

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

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

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

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

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



рабочие дни расчет просрочки матрицы

См. также

SALE! 20%

Infostart Toolkit: Инструменты разработчика 1С 8.3 на управляемых формах

Инструментарий разработчика Роли и права Запросы СКД Платформа 1С v8.3 Управляемые формы Запросы Система компоновки данных Конфигурации 1cv8 Платные (руб)

Набор инструментов программиста и специалиста 1С для всех конфигураций на управляемых формах. В состав входят инструменты: Консоль запросов, Консоль СКД, Консоль кода, Редактор объекта, Анализ прав доступа, Метаданные, Поиск ссылок, Сравнение объектов, Все функции, Подписки на события и др. Редактор запросов и кода с раскраской и контекстной подсказкой. Доработанный конструктор запросов тонкого клиента. Продукт хорошо оптимизирован и обладает самым широким функционалом среди всех инструментов, представленных на рынке.

13000 10400 руб.

02.09.2020    122168    670    389    

714

Для чего используют конструкцию запроса "ГДЕ ЛОЖЬ" в СКД на примере конфигурации 1С:ERP

Запросы СКД Платформа 1С v8.3 Запросы Система компоновки данных 1С:ERP Управление предприятием 2 Бесплатно (free)

В типовых конфигурациях разработчики компании 1С иногда используют в отчетах, построенных на СКД, такую конструкцию, как "ГДЕ ЛОЖЬ". Такая конструкция говорит о том, что данные в запросе не будут получены совсем. Для чего же нужен тогда запрос?

13.02.2024    5746    KawaNoNeko    23    

23

Набор-объект для СКД по тексту или запросу

Запросы СКД Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Абонемент ($m)

Есть список полей в виде текста, или запрос - закидываем в набор СКД.

1 стартмани

31.01.2024    2000    2    Yashazz    0    

29

Запрос 1С copilot

Инструментарий разработчика Запросы Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Абонемент ($m)

Пишем на человеческом языке, что нам надо, и получаем текст запроса на языке 1С. Используются большие языковые модели (LLM GPT) от OpenAI или Яндекс на выбор.

5 стартмани

15.01.2024    6285    31    mkalimulin    25    

50

PrintWizard: поддержка представлений ЗУП в конструкторе

Инструментарий разработчика Запросы Платформа 1С v8.3 Бесплатно (free)

Одной из интересных задач, стоящих в процессе разработки, была поддержка механизма представлений в ЗУП. Но не просто возможность исполнения запросов с ними. Основная проблема была в том, чтобы с ними было удобно работать, а именно: создавать, модифицировать и отлаживать. Кратко о том, что в итоге получилось...

14.12.2023    1742    vandalsvq    7    

29

Объектная модель запроса "Схема запроса" 2

Запросы Платформа 1С v8.3 Запросы Конфигурации 1cv8 Бесплатно (free)

Далеко уже не новый тип данных "Схема запроса". Статья о том, как использовать его "попроще". Примеры создания текста запроса с нуля и изменение имеющегося запроса.

06.12.2023    5388    user1923546    26    

43

Начните уже использовать хранилище запросов

HighLoad оптимизация Запросы

Очень немногие из тех, кто занимается поддержкой MS SQL, работают с хранилищем запросов. А ведь хранилище запросов – это очень удобный, мощный и, главное, бесплатный инструмент, позволяющий быстро найти и локализовать проблему производительности и потребления ресурсов запросами. В статье расскажем о том, как использовать хранилище запросов в MS SQL и какие плюсы и минусы у него есть.

11.10.2023    16185    skovpin_sa    14    

98
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. ZLENKO 398 25.12.14 15:58 Сейчас в теме
Вот в этом отчете по просроченной дебиторке используется расчет по рабочим дням http://infostart.ru/public/117647/

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

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

В результате все отчеты по долгам строятся за секунды.
dgolovanov; +1 Ответить
7. chmv 16.01.15 12:09 Сейчас в теме
8. vis_tmp 32 26.05.19 16:29 Сейчас в теме
Спасибо, очень хороший метод для расчета числа рабочих дней между двумя датами.
9. vis_tmp 32 26.05.19 19:50 Сейчас в теме
А как быть если дата приходится на выходной день, отсутствующий в выборке?
10. kozusenok 52 20.04.22 08:20 Сейчас в теме
Недавно тоже столкнулся с проблемой поиска ближайшего рабочего дня к дате. Запрос похож на запрос из публикации, но оставлю здесь на всякий случай.

ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ 1000000
	Календарь.ДатаКалендаря КАК ДатаКалендаря
ПОМЕСТИТЬ БанковскиеДниКалендаря
ИЗ
	РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК Календарь
ГДЕ
	(Календарь.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий)
			ИЛИ Календарь.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Предпраздничный))

УПОРЯДОЧИТЬ ПО
	Календарь.ДатаКалендаря

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

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	ДАТАВРЕМЯ(2022, 4, 1) КАК ДатаДокумента,
	5 КАК ДнейОтсрочки
ПОМЕСТИТЬ ТаблицаОплат

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	ДАТАВРЕМЯ(2022, 4, 9),
	7
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	Оплаты.ДатаДокумента КАК ДатаДокумента,
	Оплаты.ДнейОтсрочки КАК ДнейОтсрочки,
	Календарь.ДатаКалендаря КАК ДатаОплаты
ИЗ
	ТаблицаОплат КАК Оплаты
		ЛЕВОЕ СОЕДИНЕНИЕ БанковскиеДниКалендаря КАК Календарь
		ПО ((Календарь.ДатаКалендаря, Оплаты.ДнейОтсрочки) В
				(ВЫБРАТЬ
					Выборка.ДатаКалендаря КАК МаксДатаКалендаря,
					СУММА(1) КАК НомерРабочегоДня
				ИЗ
					БанковскиеДниКалендаря КАК Выборка ЛЕВОЕ СОЕДИНЕНИЕ БанковскиеДниКалендаря КАК ПодВыборка
						ПО
							ПодВыборка.ДатаКалендаря >= Оплаты.ДатаДокумента
								И ПодВыборка.ДатаКалендаря <= Выборка.ДатаКалендаря
				ГДЕ
					Выборка.ДатаКалендаря >= Оплаты.ДатаДокумента
				СГРУППИРОВАТЬ ПО
							Выборка.ДатаКалендаря))
Показать
11. kozusenok 52 20.04.22 20:47 Сейчас в теме
Если не нужно считать день даты документа то ставим "> Оплаты.ДатаДокумента"

ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ 1000000
    Календарь.ДатаКалендаря КАК ДатаКалендаря
ПОМЕСТИТЬ БанковскиеДниКалендаря
ИЗ
    РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК Календарь
ГДЕ
    (Календарь.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий)
            ИЛИ Календарь.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Предпраздничный))

УПОРЯДОЧИТЬ ПО
    Календарь.ДатаКалендаря

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

////////////////////////////////////////////////////////////­­////////////////////
ВЫБРАТЬ
    ДАТАВРЕМЯ(2022, 4, 1) КАК ДатаДокумента,
    5 КАК ДнейОтсрочки
ПОМЕСТИТЬ ТаблицаОплат

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    ДАТАВРЕМЯ(2022, 4, 9),
    7
;

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