Имя: Пароль:
1C
 
Формула ЧИСТВНДОХ в запросе
, ,
0 alekosansey
 
19.11.18
08:40
Добрый день. Есть конфигурация на 8.1 Бух для Казахстана. Есть обработка которая выполняет подсчет ГЭСВ(годовой эфективной ставки) и есть очень большой объем данных для которых нужно выполнить расчет. Подскажите как можно ускорить процесс
1 alekosansey
 
19.11.18
08:41
Процедура КнопкаВыполнитьНажатие(Кнопка)
УсловиеПункт ="";    
Запрос = Новый Запрос;
МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос.МенеджерВременныхТаблиц = МенеджерВт;
Если Подразделение.Пустая() Тогда

Иначе
    УсловиеПункт = "И ФинДвиженияПоЗБ.Пункт = &Пункт";
КонецЕсли;
Запрос.Текст = "ВЫБРАТЬ
               |    ФинДвиженияПоЗБ.Пункт КАК Пункт,
               |    ФинДвиженияПоЗБ.Регистратор.ЗБ КАК ЗБ,
               |    ФинДвиженияПоЗБ.Регистратор.Дата КАК ДатаВыдачи,
               |    ФинДвиженияПоЗБ.Регистратор.ДатаВозврата КАК ДатаВозврата,
               |    СУММА(ВЫБОР
               |            КОГДА ФинДвиженияПоЗБ.ДвижениеДС = &Выдача
               |                ТОГДА ФинДвиженияПоЗБ.Сумма
               |            ИНАЧЕ 0
               |        КОНЕЦ) КАК СуммаКредита,
               |    СУММА(ВЫБОР
               |            КОГДА ФинДвиженияПоЗБ.ДвижениеДС = &Вознаграждение
               |                    ИЛИ ФинДвиженияПоЗБ.ДвижениеДС = &КомСбор
               |                ТОГДА ФинДвиженияПоЗБ.Сумма
               |            ИНАЧЕ 0
               |        КОНЕЦ) КАК ДоходОтВыдачи
               |ПОМЕСТИТЬ ВтСырыеДанные
               |ИЗ
               |    РегистрНакопления.ФинДвиженияПоЗБ КАК ФинДвиженияПоЗБ
               |ГДЕ
               |    ФинДвиженияПоЗБ.Регистратор ССЫЛКА Документ.ВыдачаЗБ
               |    И ФинДвиженияПоЗБ.Период МЕЖДУ &НачДата И &КонДАта
               |    "+УсловиеПункт+"
               |
               |СГРУППИРОВАТЬ ПО
               |    ФинДвиженияПоЗБ.Пункт,
               |    ФинДвиженияПоЗБ.Регистратор.ЗБ,
               |    ФинДвиженияПоЗБ.Регистратор.Дата,
               |    ФинДвиженияПоЗБ.Регистратор.ДатаВозврата
               |;
               |
               |////////////////////////////////////////////////////////////////////////////////
               |ВЫБРАТЬ
               |    ВтСырыеДанные.Пункт,
               |    ВтСырыеДанные.ЗБ,
               |    ВтСырыеДанные.ДатаВыдачи,
               |    ВтСырыеДанные.ДатаВозврата,
               |    ВтСырыеДанные.СуммаКредита,
               |    ВтСырыеДанные.ДоходОтВыдачи,
               |    ВтСырыеДанные.СуммаКредита + ВтСырыеДанные.ДоходОтВыдачи КАК СуммаГашения
               |ПОМЕСТИТЬ ВтДанныеБезГЭСВ
               |ИЗ
               |    ВтСырыеДанные КАК ВтСырыеДанные
               |;
               |
               |////////////////////////////////////////////////////////////////////////////////
               |ВЫБРАТЬ
               |    ВтДанныеБезГЭСВ.Пункт,
               |    ВтДанныеБезГЭСВ.ЗБ,
               |    ВтДанныеБезГЭСВ.ДатаВыдачи,
               |    ВтДанныеБезГЭСВ.ДатаВозврата,
               |    ВтДанныеБезГЭСВ.СуммаКредита,
               |    ВтДанныеБезГЭСВ.ДоходОтВыдачи,
               |    ВтДанныеБезГЭСВ.СуммаГашения
               |ИЗ
               |    ВтДанныеБезГЭСВ КАК ВтДанныеБезГЭСВ";
              
Запрос.УстановитьПараметр("Вознаграждение",Справочники.СтатьиДвиженияДенежныхСредств.НайтиПоКоду("000000074"));
Запрос.УстановитьПараметр("КомСбор",Справочники.СтатьиДвиженияДенежныхСредств.НайтиПоКоду("000000073"));
Запрос.УстановитьПараметр("Выдача",Справочники.СтатьиДвиженияДенежныхСредств.НайтиПоКоду("000000072"));
Запрос.УстановитьПараметр("Пункт",Подразделение);
Запрос.УстановитьПараметр("НачДАта",НачДата);
Запрос.УстановитьПараметр("КОнДата",КонДата);
Выборка = Запрос.Выполнить().Выбрать();
ТабДок = Новый ТаблицаЗначений;
ТабДок.Колонки.Добавить("ЗБ",Новый ОписаниеТипов("СправочникССылка.ЗалоговыеБилеты"));
ТабДок.Колонки.Добавить("ГЭСВ",Новый ОписаниеТипов("Число"));

Пока Выборка.Следующий() Цикл
      ТекСтрока = ТабДок.Добавить();
      ТекСтрока.ЗБ = Выборка.ЗБ;
      ТекСтрока.ГЭСВ = ЧистВнДох(Выборка.ДатаВыдачи,Выборка.СуммаКредита,Выборка.ДатаВозврата,Выборка.ДоходОтВыдачи);
КонецЦикла;

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

Печать(ТЗ);

КонецПроцедуры

//Описание:
//Входные параметры:
// ДатаВыдачи,
// СуммаКредита (СуммаК),
// ДатаВозврата,
// СтавкаВознаграждение,
// Срок,
Функция ЧистВнДох(ДатаВыдачи, СуммаКредита, ДатаВозврата, СуммаВознаграждения, Точность = 0.01) экспорт
    
    Если ДатаВыдачи = Null или СуммаКредита = 0 или ДатаВозврата = null или СуммаВознаграждения = 0  Тогда
        Возврат 0;
    КонецЕсли;

    ТаблицаРасчета = Новый ТаблицаЗначений;
    ТаблицаРасчета.Колонки.Добавить("Дата", Новый ОписаниеТипов("Дата", новый КвалификаторыДаты(ЧастиДаты.Дата)));
    ТаблицаРасчета.Колонки.Добавить("РазностьДат");
    ТаблицаРасчета.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10,2)));
    
    НоваяСтрокаТаблицаРасчета = ТаблицаРасчета.Добавить();
    НоваяСтрокаТаблицаРасчета.Дата = НачалоДня(ДатаВыдачи);
    НоваяСтрокаТаблицаРасчета.РазностьДат = (НачалоДня(ДатаВыдачи) - НачалоДня(ДатаВыдачи)) / (24 * 60 * 60) / 365;
    НоваяСтрокаТаблицаРасчета.Сумма = -СуммаКредита;
    
    НоваяСтрокаТаблицаРасчета = ТаблицаРасчета.Добавить();
    НоваяСтрокаТаблицаРасчета.Дата = НачалоДня(ДатаВозврата);
    НоваяСтрокаТаблицаРасчета.РазностьДат = (НачалоДня(ДатаВозврата) - НачалоДня(ДатаВыдачи)) / (24 * 60 * 60) / 365;
    НоваяСтрокаТаблицаРасчета.Сумма = СуммаКредита+СуммаВознаграждения;
    
    //
    ПСК = 0.1;
    Сумма = 0;
    Для каждого СтрокаРасчета Из ТаблицаРасчета Цикл
        Сумма = Сумма + СтрокаРасчета.Сумма / Pow(1 + ПСК, СтрокаРасчета.РазностьДат)
    КонецЦикла;
    
    Если Сумма > 0 Тогда
        Шаг = 0.382 * ПСК;
     Иначе
        Шаг = -0.382 * ПСК;
    КонецЕсли;

    Пока (Шаг < -Точность) ИЛИ (Шаг > Точность) Цикл
        ПСК = ПСК + Шаг;
        Сумма = 0;
        Для каждого СтрокаРасчета Из ТаблицаРасчета Цикл
            Сумма = Сумма + СтрокаРасчета.Сумма / Pow(1 + ПСК, СтрокаРасчета.РазностьДат)
            
        КонецЦикла;
        Если Сумма * Шаг < 0 Тогда
            Шаг = -Шаг * 0.382;//из метода золотого сечения
        КонецЕсли;
    КонецЦикла;
    //ГЭСВ = ПСК
    Возврат Формат(ПСК*100,"ЧЦ=10; ЧДЦ=2");
    
КонецФункции
// -Sarge: 07/11/2018

Процедура Печать(ТЗ)
    ТабДокумент = Новый ТабличныйДокумент;
    
    Макет = ПолучитьМакет("Макет");
    ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
    
    ОбластьШапка.Параметры.Пункт = Подразделение;
    ОбластьШапка.Параметры.НачДата = НачДата;
    ОбластьШапка.Параметры.КонДата = КонДата;
    ТабДокумент.Вывести(ОбластьШапка);
    
    ОбластьШапкаТЗ = Макет.ПолучитьОбласть("ШапкаТЗ");
    ТабДокумент.Вывести(ОбластьШапкаТЗ);
    
    ОбластьДанныеТЗ= Макет.ПолучитьОбласть("ДанныеТЗ");
    
    Для каждого Запись Из ТЗ Цикл
    
        ОбластьДанныеТЗ.Параметры.Заполнить(Запись);
        ТабДокумент.Вывести(ОбластьДанныеТЗ);
        Сообщить("Выведен в таблицу билет :"+Запись.ЗБ);
    КонецЦикла;
    
    ТабДокумент.Показать();
    
КонецПроцедуры;
2 alekosansey
 
19.11.18
08:41
Как можно это реализовать в запросе. Если таковое возможно
3 Один С
 
19.11.18
08:55
//из метода золотого сечения

Вон оно чо.
Почувствовал свою ущербность...
4 Один С
 
19.11.18
08:57
Все не читал, но писать 365 в коде это не по пацански. Раз в 4 года будут вопросы.
5 alekosansey
 
19.11.18
09:02
Спасибо на счет 365 учту.
6 Бубка Гоп
 
19.11.18
09:08
(1)   Пока (Шаг < -Точность) ИЛИ (Шаг > Точность) Цикл

вот тут то с запросом возникнет трудность
7 Мандалай
 
19.11.18
09:33
Замер производительности что показывает?
Какие строки занимают больше всего времени?
8 alekosansey
 
22.11.18
08:35
Он просто много делает итераций внутри крайнего цикла.
9 alekosansey
 
22.11.18
08:35
update
10 alekosansey
 
22.11.18
08:37
Знаю что проблема в функции ЧИСтВнДох но где не могу понять. Подскажите пожалуйста как укоротить количество итераций
11 alekosansey
 
22.11.18
08:38
//Описание:

//Входные параметры:
// ДатаВыдачи,

// СуммаКредита (СуммаК),
// ДатаВозврата,

// СтавкаВознаграждение,
// Срок,

Функция ЧистВнДох(ДатаВыдачи, СуммаКредита, ДатаВозврата, СуммаВознаграждения, Точность = 0.01) экспорт
    
    Если ДатаВыдачи = Null или СуммаКредита = 0 или ДатаВозврата = null или СуммаВознаграждения = 0  Тогда
        Возврат 0;
    КонецЕсли;

    ТаблицаРасчета = Новый ТаблицаЗначений;
    ТаблицаРасчета.Колонки.Добавить("Дата", Новый ОписаниеТипов("Дата", новый КвалификаторыДаты(ЧастиДаты.Дата)));
    ТаблицаРасчета.Колонки.Добавить("РазностьДат");
    ТаблицаРасчета.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10,2)));
    
    НоваяСтрокаТаблицаРасчета = ТаблицаРасчета.Добавить();
    НоваяСтрокаТаблицаРасчета.Дата = НачалоДня(ДатаВыдачи);
    НоваяСтрокаТаблицаРасчета.РазностьДат = (НачалоДня(ДатаВыдачи) - НачалоДня(ДатаВыдачи)) / (24 * 60 * 60) / 365;
    НоваяСтрокаТаблицаРасчета.Сумма = -СуммаКредита;
    
    НоваяСтрокаТаблицаРасчета = ТаблицаРасчета.Добавить();
    НоваяСтрокаТаблицаРасчета.Дата = НачалоДня(ДатаВозврата);
    НоваяСтрокаТаблицаРасчета.РазностьДат = (НачалоДня(ДатаВозврата) - НачалоДня(ДатаВыдачи)) / (24 * 60 * 60) / 365;
    НоваяСтрокаТаблицаРасчета.Сумма = СуммаКредита+СуммаВознаграждения;
    
    //

    ПСК = 0.1;
    Сумма = 0;
    Для каждого СтрокаРасчета Из ТаблицаРасчета Цикл
        Сумма = Сумма + СтрокаРасчета.Сумма / Pow(1 + ПСК, СтрокаРасчета.РазностьДат)
    КонецЦикла;
    
    Если Сумма > 0 Тогда
        Шаг = 0.382 * ПСК;
     Иначе
        Шаг = -0.382 * ПСК;
    КонецЕсли;

    Пока (Шаг < -Точность) ИЛИ (Шаг > Точность) Цикл
        ПСК = ПСК + Шаг;
        Сумма = 0;
        Для каждого СтрокаРасчета Из ТаблицаРасчета Цикл
            Сумма = Сумма + СтрокаРасчета.Сумма / Pow(1 + ПСК, СтрокаРасчета.РазностьДат)
            
        КонецЦикла;
        Если Сумма * Шаг < 0 Тогда
            Шаг = -Шаг * 0.382//из метода золотого сечения

        КонецЕсли;
    КонецЦикла;
    //ГЭСВ = ПСК

    Возврат Формат(ПСК*100,"ЧЦ=10; ЧДЦ=2");
    
КонецФункции
// -Sarge: 07/11/20
12 alekosansey
 
22.11.18
08:41
точнее

//Описание:

//Входные параметры:
// ДатаВыдачи,

// СуммаКредита (СуммаК),
// ДатаВозврата,

// СтавкаВознаграждение,
// Срок,

Функция ЧистВнДох(ДатаВыдачи, СуммаКредита, ДатаВозврата, СуммаВознаграждения, Точность = 0.01) экспорт
    
    Если ДатаВыдачи = Null или СуммаКредита = 0 или ДатаВозврата = null или СуммаВознаграждения = 0  Тогда
        Возврат 0;
    КонецЕсли;

    ТаблицаРасчета = Новый ТаблицаЗначений;
    ТаблицаРасчета.Колонки.Добавить("Дата", Новый ОписаниеТипов("Дата", новый КвалификаторыДаты(ЧастиДаты.Дата)));
    ТаблицаРасчета.Колонки.Добавить("РазностьДат");
    ТаблицаРасчета.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10,2)));
    
    НоваяСтрокаТаблицаРасчета = ТаблицаРасчета.Добавить();
    НоваяСтрокаТаблицаРасчета.Дата = НачалоДня(ДатаВыдачи);
    НоваяСтрокаТаблицаРасчета.РазностьДат = (НачалоДня(ДатаВозврата) - НачалоДня(ДатаВыдачи)) / (24 * 60 * 60) / 365;
    НоваяСтрокаТаблицаРасчета.Сумма = -СуммаКредита;
    
    НоваяСтрокаТаблицаРасчета = ТаблицаРасчета.Добавить();
    НоваяСтрокаТаблицаРасчета.Дата = НачалоДня(ДатаВозврата);
    НоваяСтрокаТаблицаРасчета.РазностьДат = (НачалоДня(ДатаВозврата) - НачалоДня(ДатаВыдачи)) / (24 * 60 * 60) / 365;
    НоваяСтрокаТаблицаРасчета.Сумма = СуммаКредита+СуммаВознаграждения;
    
    //

    ПСК = 0.1;
    Сумма = 0;
    Для каждого СтрокаРасчета Из ТаблицаРасчета Цикл
        Сумма = Сумма + СтрокаРасчета.Сумма / Pow(1 + ПСК, СтрокаРасчета.РазностьДат)
    КонецЦикла;
    
    Если Сумма > 0 Тогда
        Шаг = 0.382 * ПСК;
     Иначе
        Шаг = -0.382 * ПСК;
    КонецЕсли;

    Пока (Шаг < -Точность) ИЛИ (Шаг > Точность) Цикл
        ПСК = ПСК + Шаг;
        Сумма = 0;
        Для каждого СтрокаРасчета Из ТаблицаРасчета Цикл
            Сумма = Сумма + СтрокаРасчета.Сумма / Pow(1 + ПСК, СтрокаРасчета.РазностьДат)
            
        КонецЦикла;
        Если Сумма * Шаг < 0 Тогда
            Шаг = -Шаг * 0.382//из метода золотого сечения

        КонецЕсли;
    КонецЦикла;
    //ГЭСВ = ПСК

    Возврат Формат(ПСК*100,"ЧЦ=10; ЧДЦ=2");
    
КонецФункции
// -Sarge: 07/11/20
13 Asmody
 
22.11.18
09:01
Я правильно понимаю, что ЧистВнДох() зависит от периода кредита и сумм кредита и вознаграждения? Причем, исходя из первого запроса, либо суммы равны, либо одна из них = 0, но в последнем случае страбатывает граничное условие.
Т.е. по факту у рассчета два параметра: сумма и период.
Может закешировать результат расчета в таблице и повторно не рассчитывать для одинаковых значений параметров?
Я не хочу быть самым богатым человеком на кладбище. Засыпать с чувством, что за день я сделал какую-нибудь потрясающую вещь — вот что меня интересует. Стив Джобс