|
Новый способ вычислить разницу между датами с учетом произв. календаря | ☑ | ||
---|---|---|---|---|
0
Cerera
12.09.12
✎
13:17
|
Задача - обойтись без вычисляемых полей в СКД для вычислении разницы между датами.
Мне пришлось создавать отчеты, в которых вычисляется разницы между датами в днях с учетом производственного календаря. Как вы знаете, в типовых есть регистр сведений производственного календаря и функция // Функция возвращает дату отстоящую на заданное количество рабочих дней от начальной в соответствии с //регламентированным производственным календарем // //Параметры: // ДатаНач - начальная дата // ЧислоДней - количество рабочих дней, на которое искомая дата должна отстоять от начальной // Функция ОпределитьДату(ДатаНач, ЧислоДней) Экспорт Запрос = Новый Запрос; Запрос.УстановитьПараметр("ДатаНач", ДатаНач); Запрос.УстановитьПараметр("ЧислоДней", ЧислоДней); Запрос.УстановитьПараметр("РабочийДень", Перечисления.ВидыДнейПроизводственногоКалендаря.Рабочий); Запрос.УстановитьПараметр("ПредпраздничныйДень", Перечисления.ВидыДнейПроизводственногоКалендаря.Предпраздничный); Если ЧислоДней > 0 Тогда Запрос.Текст = " |ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ " + ЧислоДней + " | РегламентированныйПроизводственныйКалендарь.ДатаКалендаря |ИЗ | РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь |ГДЕ РегламентированныйПроизводственныйКалендарь.ДатаКалендаря > &ДатаНач | И (РегламентированныйПроизводственныйКалендарь.ВидДня = &РабочийДень | ИЛИ РегламентированныйПроизводственныйКалендарь.ВидДня = &ПредпраздничныйДень) |"; Иначе ЧислоДней = -ЧислоДней; Запрос.Текст = " |ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ " + ЧислоДней + " | РегламентированныйПроизводственныйКалендарь.ДатаКалендаря |ИЗ | РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь |ГДЕ РегламентированныйПроизводственныйКалендарь.ДатаКалендаря < &ДатаНач | И (РегламентированныйПроизводственныйКалендарь.ВидДня = &РабочийДень | ИЛИ РегламентированныйПроизводственныйКалендарь.ВидДня = &ПредпраздничныйДень) |УПОРЯДОЧИТЬ ПО | ДатаКалендаря УБЫВ |"; КонецЕсли; Выборка = Запрос.Выполнить().Выбрать(); Если Выборка.Количество() = ЧислоДней Тогда Пока Выборка.Следующий() Цикл ТекДата = Выборка.ДатаКалендаря; КонецЦикла; Возврат ТекДата; КонецЕсли; Возврат Неопределено; КонецФункции Но вот в чём проблема. Использовать эту функцию в отчетах, сделанных с использованием СКД тяжело, поскольку запрос этой функции нельзя соединить с другими запросами изза грёбанной строчки |ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ " + ЧислоДней + " | РегламентированныйПроизводственныйКалендарь.ДатаКалендаря |ИЗ | РегистрСведений.РегламентированныйПроизводственныйКалендарь А число дней то для каждой строчки запроса может быть разное! А нам необходима возможность рассчитывать даты с учетом производственного календаря прямо в запросе! для того, чтобы это работало быстро, нужно создать ещё один регистр сведений в котором будут все возможные комбинации дат и в качестве ресурса будет количество дней между ними, просчитанное заранее. Что скажете про этот подход или есть более умный метод? |
|||
1
DrShad
12.09.12
✎
13:20
|
(0) пипец а не подход? у тебя время на заполнение этого нового регистра уйдет несоизмеримо больше, чем потраченное на расчет в нескольких вызовах нескольких отчетов
|
|||
2
DrShad
12.09.12
✎
13:21
|
и чем не подходит РазностьДат()
|
|||
3
Maxus43
12.09.12
✎
13:21
|
(2) надо выходные исключить видимо и праздники
|
|||
4
ChAlex
12.09.12
✎
13:22
|
(0) - да все элементарно - два набора: один требуемые периоды - второй регистр сведений со всеми датами нужного диапазона и связь по датам - потом группировка: короче описывать как реализовать больше - чем сама реализация
|
|||
5
Cerera
12.09.12
✎
13:23
|
(2)разность дат не даст тебе количество дней с учетом праздников и выходынх.
|
|||
6
Cerera
12.09.12
✎
13:26
|
(1)так регистр это заполнить можно один раз. а отчетом пользуются ежедневно многие люди. и изза вычисляемых полей это происходит долго! Вот коммерческая прибыль у нас формируется в течении нескольких минут изза этих вычисляемых полей.
|
|||
7
DrShad
12.09.12
✎
13:29
|
(5) вот она как раз с учетом дает, а за вычетом нет
|
|||
8
DrShad
12.09.12
✎
13:30
|
(6) проще уже из РазностиДат() исключать праздники и выходные
|
|||
9
ChAlex
12.09.12
✎
13:34
|
(6) - в РегистрСведений.РегламентированныйПроизводственныйКалендарь - уже все есть (там еще по-моему есть и продолжительность дня) - остается только связать с входным набором периодов
|
|||
10
dmpl
12.09.12
✎
13:34
|
(0) Как вариант - взять сумму календарных дней по условию
ДатаКалендаря МЕЖДУ ДругаяТаблица.ДатаНачала И ДругаяТаблица.ДатаОкончания Только не факт что будет быстрее вычисляемых полей. (6) А если отчет попробуют за 10 лет сформировать, что тогда? |
|||
11
dmpl
12.09.12
✎
13:37
|
(0) А вообще, можно во временную таблицу выбрать все сочетания дат в конкретном отчете, и на основании этих сочетаний формировать временную таблицу с полями ДатаНачала, ДатаОкончания, КоличествоДней, чтобы лишний раз не соединять с кучей строк производственного календаря.
|
|||
12
Cerera
12.09.12
✎
13:38
|
(10)производственный календарь обновляется раз в год. так же раз в год можно обновлять новый регистр... зато мнгновенно будет работать.
|
|||
13
Cerera
12.09.12
✎
13:39
|
(11)а если за 10 лет? долго. отчет не должен работать долго.
|
|||
14
Cerera
12.09.12
✎
13:40
|
я вот щас создам и заполню регистр и скажу на сколько гигово увеличилась база )
|
|||
15
DrShad
12.09.12
✎
13:40
|
(14) и количество записей не забудь
|
|||
16
ChAlex
12.09.12
✎
13:43
|
(14) - цитата ".. будут все возможные комбинации дат и в качестве ресурса будет количество дней между ними, просчитанное заранее. " - вы представляете себе количество комбинаций скажем хотя бы за месяц? А за год? Не забудьте между 1-м и 5-м, 2-м и 5-м и т.д. Дурное дело конечно не хитрое ... :)
|
|||
17
ChAlex
12.09.12
✎
13:47
|
+(16) - насколько помню навскидку - это будет для года 365! (!- это фактериал)
|
|||
18
dmpl
12.09.12
✎
13:47
|
(12) Понимимаешь, тут надо будет сразу на все будущее время сформировать все возможные сочетания дат. Иначе потом будешь постоянно сражаться с нулями дней в отчете.
(13) Думаешь, копаться среди 13 с лишним млн. записей будет быстрее? |
|||
19
Cerera
12.09.12
✎
13:50
|
(18)на будущее невозможно ведь неизвестны заранее праздничные дни. ну и нули так и так выходят если произв календарь не заполнен за анализируемый период. ну можно оставлять регистр заполненным только на текущий квартал. просто такие отчеты как правило нужны для рассчета дней просрочки.
|
|||
20
DrShad
12.09.12
✎
13:51
|
(19) дни просрочки вообще ни о чем, вот если расчет пеней тогда другое дело
|
|||
21
DrShad
12.09.12
✎
13:52
|
+(20) а дни просрочки интересны только в интервалах, т.е. свыше 30, 60 и более дней
|
|||
22
Cerera
12.09.12
✎
13:52
|
(20)ну пени считаются исходя из дней просрочки без учета праздничных дней и выходных.... и зарплата так же зависит от таких просрочек.
|
|||
23
DrShad
12.09.12
✎
13:54
|
(22) пеня не может начисляться на небанковский день
|
|||
24
Cerera
12.09.12
✎
13:54
|
(21)а нам интересны дни просрочки в интервалах даже свыше одного дня поскольку бонусы менеджерам от них пляшут.
|
|||
25
Cerera
12.09.12
✎
13:54
|
(23)ну я имею ввиду что менеджерам зарплату считаем так.
|
|||
26
ChAlex
12.09.12
✎
13:56
|
Вот вам примерно готовый запрос с получением выборки (без СКД) - дальше модифицируйте как угодно:
ВЫБРАТЬ Т.Ссылка КАК ВидДня, ВЫБОР КОГДА Т.Ссылка = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Воскресенье) ТОГДА 0 КОГДА Т.Ссылка = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Суббота) ТОГДА 0 КОГДА Т.Ссылка = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий) ТОГДА 8 КОГДА Т.Ссылка = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Предпраздничный) ТОГДА 7 КОГДА Т.Ссылка = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Праздник) ТОГДА 0 ИНАЧЕ 0 КОНЕЦ КАК Продолжительность ПОМЕСТИТЬ ПродолжительностьДней ИЗ Перечисление.ВидыДнейПроизводственногоКалендаря КАК Т ИНДЕКСИРОВАТЬ ПО ВидДня ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ Т.Смена КАК Смена, Т.ДатаКалендаря КАК ДатаКалендаря ПОМЕСТИТЬ Календарь ИЗ (ВЫБРАТЬ РегламентированныйПроизводственныйКалендарь.Пятидневка * ПродолжительностьДней.Продолжительность * 3600 КАК Смена, РегламентированныйПроизводственныйКалендарь.ДатаКалендаря КАК ДатаКалендаря ИЗ РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь ЛЕВОЕ СОЕДИНЕНИЕ ПродолжительностьДней КАК ПродолжительностьДней ПО РегламентированныйПроизводственныйКалендарь.ВидДня = ПродолжительностьДней.ВидДня ГДЕ РегламентированныйПроизводственныйКалендарь.ДатаКалендаря МЕЖДУ &НачалоПериода И &КонецПериода) КАК Т ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ График.ПроизводственныйЗаказ КАК Заказ, График.ПроизводственныйЗаказ.Модель КАК Модель, График.ДатаНачала, График.ДатаОкончания, График.Исполнитель, График.Количество ПОМЕСТИТЬ ГрафикРабот ИЗ РегистрСведений.ГрафикПроизводства КАК График ГДЕ График.ПериодПроизводства = &ПериодПроизводства И График.ЭтапПроизводства = &Этап ИНДЕКСИРОВАТЬ ПО Заказ, Модель ; ВЫБРАТЬ РАЗЛИЧНЫЕ График.ДатаНачала КАК ДатаНачала, График.ДатаОкончания КАК ДатаОкончания, Календарь.Смена ИЗ ГрафикРабот КАК График ЛЕВОЕ СОЕДИНЕНИЕ Календарь КАК Календарь ПО График.ДатаНачала <= Календарь.ДатаКалендаря И График.ДатаОкончания >= Календарь.ДатаКалендаря |
|||
27
DrShad
12.09.12
✎
13:56
|
(25) а (22) писал не ты, так?
|
|||
28
dmpl
12.09.12
✎
13:56
|
(19) Производственный календарь можно заполнять частями, раз в год. Тут же придется его перезаполнять постоянно, когда в очередной раз ноль вылезет в каких-нибудь местах.
Такой регистр если и делать - то с автозаполнением по факту использования данного сочетания в отчете. Т.е., нет нужного сочетания - посчитали и сохранили. Итого возвращаемся к (11). |
|||
29
Cerera
12.09.12
✎
13:57
|
(27)я под пени подразумевал штрафы которые влияют на заработок.
|
|||
30
DrShad
12.09.12
✎
13:58
|
(29) штраф и пеня разные понятия! либо выражайтесь общепринятыми, либо подробно излагайте свои подразумевания
|
|||
31
Cerera
12.09.12
✎
13:58
|
(28)не спорю. можно и в отчете. просто время. просто в (11) не доконца понял что имелось ввиду и по умолчанию подумал что та же идея.
|
|||
32
Cerera
12.09.12
✎
14:00
|
(26)а что он делает в данном случае?
|
|||
33
Feanorko
12.09.12
✎
14:02
|
Таки не понимаю, в чем проблема сделать вычисляемое поле и считать разность дат как душе угодно?
|
|||
34
ChAlex
12.09.12
✎
14:05
|
(32) - получаете массив: требуемые исходные строки (началопериода, конецПериода еще какие-то реквизиты вам нужные, например мне нужен был заказ и т.п.) - и в моем случае количество секунд каждый день в интервале с учетом выходных, предпраздничных и т.п. (можете сделать просто 1 для рабочего, 0 - для выходно, в зависимости от потребности) - все - просчитайте итоги продолжительности по ключевым полям - и вся задача
|
|||
35
ChAlex
12.09.12
✎
14:06
|
+(34) - в частности сумма рабочих дней за интервал и будет разность дат
|
|||
36
dmpl
12.09.12
✎
14:07
|
(31) Время будет только при первом формировании отчета, когда такой регистр массово будет заполняться. Тут минус в одном - придется писать код вне СКД. Да и то смотреть надо, сколько времени в реале выйдет. Может и не стоит сохранять - и достаточно просто во временную таблицу поместить, тогда можно и одним запросом обойтись.
|
|||
37
ChAlex
12.09.12
✎
14:15
|
+(34) если последний подзапрос переписать в виде:
ВЫБРАТЬ РАЗЛИЧНЫЕ Т.ДатаНачала КАК ДатаНачала, Т.ДатаОкончания КАК ДатаОкончания, Сумма(Т.Смена) КАК РазностьДат ИЗ (ВЫБРАТЬ РАЗЛИЧНЫЕ График.ДатаНачала КАК ДатаНачала, График.ДатаОкончания КАК ДатаОкончания, Календарь.Смена ИЗ ГрафикРабот КАК График ЛЕВОЕ СОЕДИНЕНИЕ Календарь КАК Календарь ПО График.ДатаНачала <= Календарь.ДатаКалендаря И График.ДатаОкончания >= Календарь.ДатаКалендаря) КАК Т СГРУППИРОВАТЬ ПО Т.ДатаНачала,Т.ДатаОкончания То получаете вам нужные данные, в предположении что "Смена" - формировали 1 - для рабочего дня и 0 - для выходного. Усе!! |
|||
38
Cerera
12.09.12
✎
14:40
|
(33)ну не дело это... долго работают вычисляемые поля и это уже не запрос. а запрос переносим на другие отчеты... а как вычисляемое поле перенесёшь куда-нибудь помимо СКД?
|
|||
39
Feanorko
12.09.12
✎
14:43
|
(38) понял)
|
|||
40
Kashemir
12.09.12
✎
15:07
|
Тяжелый запрос - быстро вряд ли будет работать, для этого надо как минимум добавить ограничение на максимальную острочку платежа в календарных днях
|
|||
41
Cerera
12.09.12
✎
15:26
|
Кстати вот что сделал
Док=Документы.УставнокаКоличестваРабочихДнейМеждуДатамиСУчетомПроизводственногоКалендаря.СоздатьДокумент(); Док.Дата=ТекущаяДата(); Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | РегламентированныйПроизводственныйКалендарь.ДатаКалендаря |ИЗ | РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь |ГДЕ | РегламентированныйПроизводственныйКалендарь.ДатаКалендаря МЕЖДУ &Дата1 И &Дата2"; Запрос.УстановитьПараметр("Дата1",НачПериода); Запрос.УстановитьПараметр("Дата2",КонецДня(КонПериода)); ТЗ = Запрос.Выполнить().Выгрузить(); Инд=ТЗ.Количество()-1; Пока Инд>=0 Цикл Ёнд=0; Пока Ёнд<=Инд Цикл НовСтр=Док.РабочиеДниМеждуДатами.Добавить(); НовСтр.НачДата=ТЗ[Ёнд].ДатаКалендаря; НовСтр.КонДата=ТЗ[Инд].ДатаКалендаря; НовСтр.КоличествоДней=ЗаполнениеДокументов.ЧислоРабочихДней(НовСтр.НачДата,НовСтр.КонДата); Ёнд=Ёнд+1; КонецЦикла; Инд=Инд-1; КонецЦикла; Док.Записать(РежимЗаписиДокумента.Запись); |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |