gifts2017

Добавить к дате рабочие дни в запросе

Опубликовал Александр Андреев (INTECH RU) в раздел Программирование - Практика программирования

Был отчет, в котором к неким датам прибавлялось 15 дней функцией ДобавитьКДате(). Но вот понадобилось добавлять к дате не все дни, а только рабочие. Сделал запрос, может быть кому понадобится

 Собственно запрос получился такой: 

 ВЫБРАТЬ Даты.Дата,

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

СГРУППИРОВАТЬ ПО
	РегламентированныйПроизводственныйКалендарь1.ДатаКалендаря,
	Даты.Дата

ИМЕЮЩИЕ
	МАКСИМУМ(РегламентированныйПроизводственныйКалендарь.ДатаКалендаря) = РегламентированныйПроизводственныйКалендарь1.ДатаКалендаря

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

Вот пример работы для одной даты 28.11.2012

       
Дата КоличествоРабочихДней ДатаКалендаря ДатаКалендаряДляГруппировки  
28.11.2012 1 28.11.2012 28.11.2012  
28.11.2012 2 29.11.2012 29.11.2012  
28.11.2012 3 30.11.2012 30.11.2012  
28.11.2012 4 03.12.2012 03.12.2012  
28.11.2012 5 04.12.2012 04.12.2012  
28.11.2012 6 05.12.2012 05.12.2012  
28.11.2012 7 06.12.2012 06.12.2012  
28.11.2012 8 07.12.2012 07.12.2012  
28.11.2012 9 10.12.2012 10.12.2012  
28.11.2012 10 11.12.2012 11.12.2012  
28.11.2012 11 12.12.2012 12.12.2012  
28.11.2012 12 13.12.2012 13.12.2012  
28.11.2012 13 14.12.2012 14.12.2012  
28.11.2012 14 17.12.2012 17.12.2012  
28.11.2012 15 18.12.2012 18.12.2012  
28.11.2012 16 19.12.2012 19.12.2012  
28.11.2012 17 20.12.2012 20.12.2012  
28.11.2012 18 21.12.2012 21.12.2012  
28.11.2012 19 24.12.2012 24.12.2012  
28.11.2012 20 25.12.2012 25.12.2012  
28.11.2012 21 26.12.2012 26.12.2012  
28.11.2012 22 27.12.2012 27.12.2012  

 

В конец запроса осталось добавить условие

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

и отобрать данные по нужному количеству рабочих дней в параметре "РабочихДней"

Ну и в конце полная верия запроса, если захочется опробовать в консоли запросов

ВЫБРАТЬ
	РегламентированныйПроизводственныйКалендарь.ДатаКалендаря КАК Дата
ПОМЕСТИТЬ Даты
ИЗ
	РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь
ГДЕ
	РегламентированныйПроизводственныйКалендарь.ДатаКалендаря В(&ВходящиеДаты)
;

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

СГРУППИРОВАТЬ ПО
	РегламентированныйПроизводственныйКалендарь1.ДатаКалендаря,
	Даты.Дата

ИМЕЮЩИЕ
	МАКСИМУМ(РегламентированныйПроизводственныйКалендарь.ДатаКалендаря) = РегламентированныйПроизводственныйКалендарь1.ДатаКалендаря
	И КОЛИЧЕСТВО(РАЗЛИЧНЫЕ РегламентированныйПроизводственныйКалендарь.ДатаКалендаря) = &РабочихДней

 

См. также

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

Комментарии

1. Александр Медведев (anig99) 17.12.12 11:05
И в чём новизна? И здесь, и на других форумах тема широко обсуждалась... Данное решение - самое банальное.
2. Александр Андреев (INTECH RU) 17.12.12 11:10
На новизну не претендовал, просто не нашел решение, когда понадобилось. Можно ссылку на обсуждение?
4. Игор Мудрицкий (Zas1402) 20.12.12 17:16
На новизну не претендовал, просто не нашел решение, когда понадобилось.

Полезная тема.
5. Антон Шелашский (Aesh) 26.12.12 15:40
В том-то и оно, что обсуждалось, типа "Кури ...". Тут парень конкретно написал. Я помню раньше еще писал, но потом какое-то время не работал с 1С, сейчас на свое взглянул (а там еще с планом счетов связано), аж паника продернула, вспоминал бы дня два! Спасибо, ооочень выручил, так бы все писали, а не "Кури..."
6. Азбука Морзе 25.04.13 17:18
Идея добавить к дате рабочие дни очень помогла при разработке отчетов, связанных с банковскими днями. Спасибо.
NazarovV; +1 Ответить
7. Роман Попов (popro) 20.06.13 16:59
как правильно определить глубину дней чтобы не было слишком много или недостаточно?
8. Александр Андреев (INTECH RU) 20.06.13 17:08
Ну здесь дело в праздниках, если взять, например, какое-нибудь 21.12.2012, то глубина 15 дней не достаточна из-за долгих январских праздников - вот только исходя из таких нюансов. Поэтому Глубина = 15 дней + Максимум количества праздников, вот как-то так
9. Павел (Yimaida) 19.08.13 18:56
Немного допилил запрос, чтобы можно было отнять дату. Автору +, единственное внятное рабочее решение, которое я нашел в инете по этой теме ("скопировал и работает").

ВЫБРАТЬ
	РегламентированныйПроизводственныйКалендарь.ДатаКалендаря КАК Дата
ПОМЕСТИТЬ Даты
ИЗ
	РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь
ГДЕ
	РегламентированныйПроизводственныйКалендарь.ДатаКалендаря В(&ВходящиеДаты)
;

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

СГРУППИРОВАТЬ ПО
	РегламентированныйПроизводственныйКалендарь1.ДатаКалендаря,
	Даты.Дата

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


или так

ВЫБРАТЬ
	РегламентированныйПроизводственныйКалендарь.ДатаКалендаря КАК Дата
ПОМЕСТИТЬ Даты
ИЗ
	РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь
ГДЕ
	РегламентированныйПроизводственныйКалендарь.ДатаКалендаря В(&ВходящиеДаты)
;

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

СГРУППИРОВАТЬ ПО
	РегламентированныйПроизводственныйКалендарь1.ДатаКалендаря,
	Даты.Дата

ИМЕЮЩИЕ
	ВЫБОР
		КОГДА &РабочихДней < 0
			ТОГДА МИНИМУМ(РегламентированныйПроизводственныйКалендарь.ДатаКалендаря) = РегламентированныйПроизводственныйКалендарь1.ДатаКалендаря
		ИНАЧЕ МАКСИМУМ(РегламентированныйПроизводственныйКалендарь.ДатаКалендаря) = РегламентированныйПроизводственныйКалендарь1.ДатаКалендаря
	КОНЕЦ И
	ВЫБОР
		КОГДА &РабочихДней < 0
			ТОГДА КОЛИЧЕСТВО(РАЗЛИЧНЫЕ РегламентированныйПроизводственныйКалендарь.ДатаКалендаря) = -&РабочихДней
		ИНАЧЕ КОЛИЧЕСТВО(РАЗЛИЧНЫЕ РегламентированныйПроизводственныйКалендарь.ДатаКалендаря) = &РабочихДней
	КОНЕЦ
...Показать Скрыть
10. Денис Луцик (NAKIS) 18.12.13 17:23
новое решение или старое - но мне помогло. Автору спасибо огромное))))
11. ghOst Bu (ilonnaa) 12.02.14 10:45
Автору +, жаль для бух 3.0 не подходит)
12. Александр Андреев (INTECH RU) 12.02.14 11:58
(11) ilonnaa, а что там не так, регистр календаря что-ли по-другому называется?
13. ghOst Bu (ilonnaa) 12.02.14 21:17
(12) INTECH RU, Там регистр по другому называется, + производственный календарь это справочник) ну все получилось, чуть запрос переписав, выложить не могу сервер выключился что-то( завтра если не забуду.
14. qwertor (qwertor) 06.08.14 13:28
оставлю для коллекции вариант для Бух.3
Функция  ОтсчитатьРабочиеДни(ДатаОтсчета,Отсрочка)
	
Запрос = Новый Запрос;
Запрос.Текст = "Select 
	|	ДанныеПроизводственногоКалендаря.ПроизводственныйКалендарь,
	|	ДанныеПроизводственногоКалендаря.Дата,
	|	ДанныеПроизводственногоКалендаря.Год,
	|	ДанныеПроизводственногоКалендаря.ВидДня,
	|	ДанныеПроизводственногоКалендаря.ДатаПереноса
	|
	|into 
	| cal	
	|from 
	|	РегистрСведений.ДанныеПроизводственногоКалендаря КАК ДанныеПроизводственногоКалендаря
	|where 
	|   ДанныеПроизводственногоКалендаря.Дата between &ДатаОтсчета
	|  and DateAdd(&ДатаОтсчета, день, &Отсрочка*2 + 12)
	|;
	|	
	|Select  
	|min(дата) датаОтсрочки  
	|from(
	|Select 
	|
	|c1.дата дата,
	|
	|count(*) -1 РабочихДней
	|
	|from cal c1
	|left join   cal c2
	|on (c2.ВидДня = value(Перечисление.ВидыДнейПроизводственногоКалендаря.Предпраздничный) or c2.ВидДня = value(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий))
	|and c1.дата>=c2.дата
	|group by c1.дата
	|having count(*)= &Отсрочка+1
	|) tt
	|group by  РабочихДней";
попытка	
Запрос.УстановитьПараметр("ДатаОтсчета", ДатаОтсчета);
Запрос.УстановитьПараметр("Отсрочка", Отсрочка);
Результат = Запрос.Выполнить().Выгрузить();
Возврат Результат[0].датаОтсрочки; 
исключение
конецпопытки;

конецФункции
...Показать Скрыть
u_n_k_n_o_w_n; +1 Ответить
15. Captain Obvious (Obvious) 06.08.14 13:46
Идея ок. Но задачка редко стоит просто отсечь празники. Рекомендую брать с графиков работы. Так как бух вряд ли полезет править произв календарь (он заходит правит в графике. а произв календарь виржин) ИМХО
16. Наталья Касперович (nik-boss) 28.05.15 09:43
Спасибо Вам большое! Очень помогло быстро сделать необходимый отчет!
17. Николай (Nikola1147) 12.02.16 11:21
ко второму соединению
полезно будет добавить условие типа (отмечено жирным)

ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь1
ПО РегламентированныйПроизводственныйКалендарь.ДатаКалендаря <= РегламентированныйПроизводственныйКалендарь1.ДатаКалендаря
И (ДОБАВИТЬКДАТЕ(РегламентированныйПроизводственныйКалендарь.ДатаКалендаря, ДЕНЬ, &ГлубинаДней) > РегламентированныйПроизводственныйКалендарь1.ДатаКалендаря)


иначе много доп сведений (дат) добавляется, которые не очень-то нужны,
разница в скорострельности ощутима на 3-х значениях В (&ВходящиеДаты)

Автору спасибо, очень помогло
u_n_k_n_o_w_n; +1 Ответить
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа