Имя: Пароль:
1C
 
Определить n-ный рабочий день после определенной даты в запросе.
0 patria0muerte
 
15.12.15
07:00
Доброго времени суток, коллеги!

Задача есть такая:

Имеется табличка (Т1) с документами и количеством дней вида:

ТипДокумента / Дата / КоличествоДней
Реализация товаров и услуг / 10.12.2015 / 3

Также под рукой есть регламентированный производственный календарь (Таблица - Т2) без выходных дней вида:
ДатаКалендаря
09.12.2015
10.12.2015
11.12.2015
14.12.2015
15.12.2015
16.12.2015

Т.е. табличка всех дней кроме сб и вс (ну и праздников).

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

В данном случае на выходе должна быть строка:

ТипДокумента / Дата / КоличествоДней / ДатаСогласования
Реализация товаров и услуг / 10.12.2015 / 3  / 15.12.2015

И чет никак мысль не идет, как ее так присоединить. Все в голову лезет ДобавитьКДате, но оно не подходит, т.к. нужно пропускать выходные дни.

Есть у кого какие идеи как это в запросе можно реализовать?
1 ИС-2
 
naïve
15.12.15
07:07
(0) через РС РегламентированныйПроизводственныйКалендарь
2 patria0muerte
 
15.12.15
07:10
(1) Уже использую, о чем собственно и написал в (0).
3 patria0muerte
 
15.12.15
07:32
Вроде получилось. Запрос примерно такого вида:

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

СГРУППИРОВАТЬ ПО
    ВТДокументы.ТипДокумента,
    ВТДокументы.ДокументСсылка,
    ВТДокументы.ВидСогласования,
    ВТДокументы.ДатаОтправкиЭталон,
    ВТДокументы.КоличествоДнейДляСогласования

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

По производительности правда надо будет еще потестировать. Но так - работает
4 Лефмихалыч
 
15.12.15
08:39
(3) лучше НАЧАЛОПЕРИОДА(ВТДокументы.ДатаОтправкиЭталон, ДЕНЬ) получать при формировании ВТ, чем при соединении
5 Лефмихалыч
 
15.12.15
08:42
а что вернет РазностьДат(), когда второй аргумент null?
6 patria0muerte
 
15.12.15
09:09
(4) Согласен, так и поступил вообщем. В (3) "примерный" вариант.

(5) Фигню какую-то вернет, к бабке не ходи.
Благодарю за коммент. Надо будет как-то заранее исключить возможность появления там NULL.
7 Лефмихалыч
 
15.12.15
09:12
(6) Null и вернет. Соответственно ГДЕ превращает соединение во внутреннее. Учитывай это.
8 Molinor
 
15.12.15
09:19
А точно ли будет работать правильно этот запрос?

Например:
Реализация товаров и услуг / 10.12.2015 / 7

Также под рукой есть регламентированный производственный календарь (Таблица - Т2) без выходных дней вида:
ДатаКалендаря
09.12.2015
10.12.2015
11.12.2015
14.12.2015
15.12.2015
19.12.2015
20.12.2015
21.12.2015
24.12.2015
25.12.2015


Вернёт запрос 19 декабря, насколько я понял, но это же неверно?
9 patria0muerte
 
15.12.15
09:30
(8) Хм, действительно, спасибо. Вернет 19е. А должен - 24е. Подумаем.
10 NcSteel
 
15.12.15
09:33
(0) Зачем в запросе, правильнее это делать кодом
11 Лефмихалыч
 
15.12.15
09:34
Думаю, тут вариант только делать через нумерацию строк в запросе
12 Timon1405
 
15.12.15
09:35
(0) все уже придумано. БСП -> КалендарныеГрафики.ПолучитьМассивДатПоКалендарю
13 NcSteel
 
15.12.15
09:36
(11) Нафига насиловать сервер, когда проще и быстрее получить в коде
14 NcSteel
 
15.12.15
09:37
(13) Инструмент должен соответствовать задаче
15 Лефмихалыч
 
15.12.15
09:37
(13) зачем насиловать клиента, если можно сделать все на сервере?
16 NcSteel
 
15.12.15
09:38
(15) об этом и говорю, можно и на сервере сделать, но не извращениями типа "нумерация строк в запросе".
17 NcSteel
 
15.12.15
09:39
(16) + Это уже напоминает фриков, которые ради того, что бы использовать фишку втыкают ее во все места....
18 Лефмихалыч
 
15.12.15
09:40
(16) это не извращения
19 Лефмихалыч
 
15.12.15
09:42
в общем, чтобы это сделать в запросе, надо, чтобы рабочие даты календаря были пронумерованы. Без этого их просто не по чему соединять.
20 patria0muerte
 
15.12.15
09:46
Пронумеровал. Вот этим запросом:

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

СГРУППИРОВАТЬ ПО
    ВТГрафикРаботы.СледующийКонецРабочегоДня,
    ВТГрафикРаботы.ВидДня,
    ВТГрафикРаботы.СледующийВидДня,
    ВТГрафикРаботы.НачалоДня,
    ВТГрафикРаботы.КонецДня,
    ВТГрафикРаботы.ДатаКалендаря,
    ВТГрафикРаботы.СледующийРабочийДень,
    ВТГрафикРаботы.СледующееНачалоРабочегоДня

Тут еще следующий день прилепляется, т.к. помимо приращения дней еще приращение часов есть. Но это уже нюансы.
21 patria0muerte
 
15.12.15
09:49
(16) Что извращенного может быть в соединении двух таблиц?
22 НЕА123
 
15.12.15
09:50
Выбрать Максимум(ДД) ИЗ (ВЫБРАТЬ ПЕРВЫЕ #ЧИСЛОДНЕЙ# ДАТА ИЗ
РСКалендарь ГДЕ ДД >= &ДДНачала)
23 НЕА123
 
15.12.15
09:51
+(22)
не. без упорядочивание не пойдет.
24 НЕА123
 
15.12.15
09:51
ВЫБРАТЬ ПЕРВЫЕ #ЧИСЛОДНЕЙ# ДАТА ИЗ
РСКалендарь ГДЕ ДД >= &ДДНачала
упорядочить по ДД возр
25 patria0muerte
 
15.12.15
09:52
(22) В целом не пойдет, т.к. строка с документом не одна и #ЧИСЛОДНЕЙ# всегда разное будет...
26 Лефмихалыч
 
15.12.15
10:03
держи, автор. Оптимизируй только:

<code>
ВЫБРАТЬ
    ВТ.Объект,
    ВТ.Дата,
    ВТ.Количество
ПОМЕСТИТЬ ВТ
ИЗ
    &ВТ КАК ВТ
;

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

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

СГРУППИРОВАТЬ ПО
    ДниКалендаря.Объект,
    ДниКалендаря.Дата,
    ДниКалендаря.ДатаКалендаря,
    ДниКалендаря.Количество

ИМЕЮЩИЕ
    КОЛИЧЕСТВО(ДниКалендаря1.ДатаКалендаря) <= ДниКалендаря.Количество
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    КоличествоРабочихДней.Объект КАК Объект,
    КоличествоРабочихДней.Дата,
    КоличествоРабочихДней.Количество,
    МАКСИМУМ(КоличествоРабочихДней.ДатаКалендаря) КАК ВотЭтоТвояЭннаяДата
ИЗ
    КоличествоРабочихДней КАК КоличествоРабочихДней

СГРУППИРОВАТЬ ПО
    КоличествоРабочихДней.Дата,
    КоличествоРабочихДней.Количество,
    КоличествоРабочихДней.Объект
</code>
27 Лефмихалыч
 
15.12.15
10:03
(17) :-р
28 NcSteel
 
15.12.15
10:05
(21) В нецелесообразности. У автора есть таблица , зачем ее передавать в запрос и потом еще телодвижения делать, если достаточно один раз получить производственный график и кодом все подобрать
29 Лефмихалыч
 
15.12.15
10:06
(28) ты просто боишься соединять таблицу саму с собой
30 Timon1405
 
15.12.15
10:07
(28) Это называется квайрофапия)
31 NcSteel
 
15.12.15
10:07
(29) ты видимо читал мою медицинскую карту ?  )
32 patria0muerte
 
15.12.15
10:07
(26) Благодарю. Уже сам тут кой чего нарулил. Итоговый вариант выложу на память.
33 patria0muerte
 
21.12.15
10:22
Вообщем, итоговый вариант таков:


ВЫБРАТЬ
    РегламентированныйПроизводственныйКалендарь.ДатаКалендаря КАК РабочийДень,
    ДОБАВИТЬКДАТЕ(РегламентированныйПроизводственныйКалендарь.ДатаКалендаря, ЧАС, 9) КАК НачалоРабочегоДня,
    ВЫБОР
        КОГДА РегламентированныйПроизводственныйКалендарь.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Предпраздничный)
            ТОГДА ДОБАВИТЬКДАТЕ(РегламентированныйПроизводственныйКалендарь.ДатаКалендаря, ЧАС, 17)
        ИНАЧЕ ДОБАВИТЬКДАТЕ(РегламентированныйПроизводственныйКалендарь.ДатаКалендаря, ЧАС, 18)
    КОНЕЦ КАК КонецРабочегоДня
ПОМЕСТИТЬ ВТКалендарь
ИЗ
    РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь
ГДЕ
    РегламентированныйПроизводственныйКалендарь.ВидДня В (ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий), ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Предпраздничный))
    И РегламентированныйПроизводственныйКалендарь.ДатаКалендаря МЕЖДУ &НачалоПериода И &КонецПериода
;

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

СГРУППИРОВАТЬ ПО
    ВТКалендарь.РабочийДень,
    ВТКалендарь.КонецРабочегоДня,
    ВТКалендарь.НачалоРабочегоДня
;

////////////////////////////////////////////////////////////////////////////////
УНИЧТОЖИТЬ ВТКалендарь
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    СрокиСогласования.ВидСогласования,
    СрокиСогласования.КоличествоЧасовСогласования,
    СрокиСогласования.КоличествоДнейСогласования,
    ТИПЗНАЧЕНИЯ(СрокиСогласования.ПустаяСсылка) КАК ТипСсылки
ПОМЕСТИТЬ ВТСрокиСогласования
ИЗ
    РегистрСведений.ПРС_СрокиСогласования КАК СрокиСогласования
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ РАЗРЕШЕННЫЕ
    ИсторияОтправкиУведомленийПоСогласованиюСрезПоследних.ДокументСсылка,
    ИсторияОтправкиУведомленийПоСогласованиюСрезПоследних.ВидСогласования,
    ИсторияОтправкиУведомленийПоСогласованиюСрезПоследних.Ответственный,
    ИсторияОтправкиУведомленийПоСогласованиюСрезПоследних.ДатаОтправки,
    ИсторияОтправкиУведомленийПоСогласованиюСрезПоследних.ОтветственныйЗаОтправкуУведомления,
    ИсторияОтправкиУведомленийПоСогласованиюСрезПоследних.ЗапросНаСогласование
ПОМЕСТИТЬ ВТКСогласованию
ИЗ
    РегистрСведений.ПРС_ИсторияОтправкиУведомленийПоСогласованию.СрезПоследних(
            ,
            ДатаОтправки МЕЖДУ &НачалоПериода И &КонецПериода
                И Ответственный = &ТекущийПользователь) КАК ИсторияОтправкиУведомленийПоСогласованиюСрезПоследних
ГДЕ
    ИсторияОтправкиУведомленийПоСогласованиюСрезПоследних.ДатаСогласования = ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0)
;

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

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

СГРУППИРОВАТЬ ПО
    ВТЕстьСрокиСогласования.ДатаОтправки,
    ВТЕстьСрокиСогласования.ДеньОтправки,
    ВТЕстьСрокиСогласования.ДокументСсылка,
    ВТЕстьСрокиСогласования.КоличествоЧасовСогласования,
    ВТЕстьСрокиСогласования.КоличествоДнейСогласования,
    ВТЕстьСрокиСогласования.ВремяОтправки
;

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

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

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

[\1C]