• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

    На последнюю неделю приходится экзамен, где нужно будет показать свои навыки, взломав ряд уязвимых учебных сайтов, и добыть флаги. Успешно сдавшие экзамен получат сертификат.

    Запись на курс до 25 апреля. Получить промодоступ ...

Медленная работа запроса

  • Автор темы LEVENTENOK
  • Дата начала
L

LEVENTENOK

1С 7.7

есть регистр остатков "ОстаткиТоваров" с измерением "Товар" и ресурсом "ОстатокТовара".

есть таблица значений - список отобранных товаров ТЗ

нужно по каждому товару получить чило - количество дней в заданном периоде, когда ОстатокТовара был положительным.
типа
Если ОстатокТовара (за этот день) > 0 Тогда КолвоДней = КолвоДней + 1;

решил так:

РегОст1=СоздатьОбъект("Регистр.ОстаткиТоваров");
РегОст1.ВременныйРасчет();

ТЗ.ВыбратьСтроки();
Пока ТЗ.ПолучитьСтроку() = 1 Цикл
КД = 0;
Дата1 = ВыбНачПериода -1;
РегОст1.УстановитьФильтр("Товар",,);
РегОст1.УстановитьЗначениеФильтра("Товар",ТЗ.Товар);
Пока Дата1 < ВыбКонПериодаТА Цикл
Дата1 = Дата1 + 1;
РассчитатьРегистрыНа(Дата(Дата1));
Колво = РегОст1.СводныйОстаток(ТЗскул.Товар, , , "ОстатокТовара");
Если Число(Колво) > 0 Тогда
КД = КД +1;
КонецЕсли
КонецЦикла;
ТЗ.КолДН = КД;
КонецЦикла;

работает очень-очень медленно, да оно и понятно. на таблице в 2500 товаров и за период - месяц - не дождался...
как ускорить? очень нужно!

заранее спасибо.
 
V

vbs

Работает у тебя медленно из-за постоянного пересчета регистров

Попробуй примерно такой запрос :
ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|Период с ВыбНачПериода по ВыбКонПериода;
|Товар = Регистр.ОстаткиТоваров.Товар;
|ОстатокТовара = Регистр.ОстаткиТоваров.ОстатокТовара;
|Условие (Товар в ТЗ.Товар);
|Группировка Товар;
|Группировка День;";
 
P

puh14

ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|Период с ВыбНачПериода по ВыбКонПериода;
|Без Итогов;
|Товар = Регистр.ОстаткиТоваров.Товар;
|ОстатокТовара = Регистр.ОстаткиТоваров.ОстатокТовара;
|Регистратор = Регистр.ОстаткиТоваров.ТекущийДокумент;
|Условие (Товар в ТЗ.Товар);
|Функция ОстатокРег = КонОст(ОстатокТовара);
|Группировка Товар Без Групп;
|Группировка Регистратор;";
ТЗ2 = создатьОбъект("ТаблицаЗначений");
запрос.Выгрузить(ТЗ2);
ТЗ2.Свернуть("Товар,Регистратор","");
Тз2.НоваяКолонка("ЧислоДней");
Тз2.ВыбратьСтроки();
Пока для ааа=1 по ТЗ2.КоличествоСтрок() Цикл
ТЗ2.ПолучитьСтрокуПоНомеру(ааа);
Если Тз2.ОстатокРег<=0 Тогда
Тз2.УдалитьСтроку(ааа);
ааа = ааа-1;
Иначе
Тз2.ЧислоДней = Тз2.Регистратор.ДатаДок - ВыбНачПериода;
КонецЕсли;
КонецЦикла;


вот как-то так.. По идее должен выдавать конечные остатки на регистраторы, которые есть документы у которых есть дата. Надо чтоб была дата начала отчета, если таковой нет - тогда извращаться.


ааа - не совсем так, надо учесть приходы. попозже напишу
 
P

puh14

корректно-корректно. я так всегда ТЗ сокращаю - работает без косяков. я же не с текущей строкой работаю а через получитьстрокупономеру()


а вот запрос у меня неправильный, как и сокращение. Правильный скоро будет
 
L

LEVENTENOK

Очень-очень жду. на самом деле - есть еще приходы...1-го было 10, потом 2-го ушло 2, потом 3-го ушло 8, потом 5-го пришло 10, потом 10-го ушло 10.
количество дней = 9
 
P

puh14

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|Период с ВыбНачПериода по ВыбКонПериода;
|Без Итогов;
|Товар = Регистр.ОстаткиТоваров.Товар;
|ОстатокТовара = Регистр.ОстаткиТоваров.ОстатокТовара;
|Док = Регистр.ОстаткиТоваров.ТекущийДокумент;
|Группировка Товар Без Групп;
|Группировка Док;
|Функция ОстатокНач = НачОст(ОстатокТовара);
|Функция ОстатокПр = Приход(ОстатокТовара);
|Функция ОстатокРс = Расход(ОстатокТовара);
|Условие (Товар в ТЗ.Товар);";
Запрос.Выполнить(ТекстЗапроса);
ТЗ2 = создатьОбъект("ТаблицаЗначений");
запрос.Выгрузить(ТЗ2);
ТЗ2.Свернуть("Товар,Док","ОстатокНач,ОстатокПр,ОстатокРс,ОстатокКон");
Тз2.Сортировать("+Товар,+Док");
Тз2.НоваяКолонка("ДокКонца");
Тз2.НоваяКолонка("ЧислоДней");
Тз2.ВыбратьСтроки();
для ааа=1 по ТЗ2.КоличествоСтрок() Цикл
ТЗ2.ПолучитьСтрокуПоНомеру(ааа);
Если Тз2.Товар <>Тз2.ПолучитьЗначение(ааа+1,"Товар") Тогда
Продолжить;
Иначе
Текущийостаток = ТЗ2.ОстатокНач+ТЗ2.ОстатокПр + Тз2.ПолучитьЗначение(ааа+1,"ОстатокПр")-Тз2.ПолучитьЗначение(ааа+1,"ОстатокРс");
Если ТекущийОстаток>0 Тогда
ТЗ2.ОстатокНач = ТекущийОстаток;
ТЗ2.УдалитьСтроку(ааа+1);
ААА = ааа-1;
ИначеЕсли ТекущийОстаток=0 Тогда
ТЗ2.ОстатокНач = 0;
ТЗ2.ДокКонца = Тз2.ПолучитьЗначение(ааа+1,"Док");
ТЗ2.УдалитьСтроку(ааа+1);


Иначе
ТЗ2.ОстатокНач = ТекущийОстаток;
ТЗ2.ДокКонца = Тз2.ПолучитьЗначение(ааа+1,"Док");
ТЗ2.УдалитьСтроку(ааа+1);
ААА = ааа-1;

КонецЕсли;
КонецЕсли;
КонецЦикла;



Вот как-то так. Посмотри на ТЗ2 до сворачивания.Там все движения.
по идее алгоритм свертки тз правильный - но что-то я не учел , некорректно пашет. это ты уж сам.
после свертки действия простые новая колонка с числодней заполняется разницей дат документов или разницей документов и периодов. а потом ТЗ сворачиваетсяпо колонкам товар и числодней.

как время будет тож повожусь с сверткой - пока со временем худо
 
P

puh14

//*******************************************
Процедура Сформировать()
Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|Период с ВыбНачПериода по ВыбКонПериода;
|Без Итогов;
|Товар = Регистр.ОстаткиТоваров.Товар;
|ОстатокТовара = Регистр.ОстаткиТоваров.ОстатокТовара;
|Док = Регистр.ОстаткиТоваров.ТекущийДокумент;
|Группировка Товар Без Групп;
|Группировка Док;
|Функция ОстатокНач = НачОст(ОстатокТовара);
|Функция ОстатокПр = Приход(ОстатокТовара);
|Функция ОстатокРс = Расход(ОстатокТовара);
|Условие (Товар в ТЗ.Товар);";
Запрос.Выполнить(ТекстЗапроса);
ТЗ2 = создатьОбъект("ТаблицаЗначений");
запрос.Выгрузить(ТЗ2);
ТЗ2.Свернуть("Товар,Док","ОстатокНач,ОстатокПр,ОстатокРс,ОстатокКон");
Тз2.Сортировать("+Товар,+Док",1);
Тз2.НоваяКолонка("ДокКонца");
Тз2.НоваяКолонка("ЧислоДней");
Тз2.ВыбратьСтроки();
Текущийостаток =0;
для ааа=1 по ТЗ2.КоличествоСтрок() Цикл
ПОПЫТКА
ТЗ2.ПолучитьСтрокуПоНомеру(ааа+1);
иСКЛЮЧЕНИЕ
Прервать;
КонецПопытки;
ТЗ2.ПолучитьСтрокуПоНомеру(ааа);
Если Тз2.Товар <>Тз2.ПолучитьЗначение(ааа+1,"Товар") Тогда
ТекущийОстаток = 0;
Продолжить;
Иначе
Текущийостаток = ТекущийОстаток + ТЗ2.ОстатокНач+ТЗ2.ОстатокПр - ТЗ2.ОстатокРс + Тз2.ПолучитьЗначение(ааа+1,"ОстатокНач") + Тз2.ПолучитьЗначение(ааа+1,"ОстатокПр")-Тз2.ПолучитьЗначение(ааа+1,"ОстатокРс");
Если ТекущийОстаток>0 Тогда
ТЗ2.ОстатокНач = 0;
ТЗ2.ОстатокПр =0;
ТЗ2.ОстатокРс =0;
ТЗ2.УдалитьСтроку(ааа+1);
ААА = ааа-1;
ИначеЕсли ТекущийОстаток=0 Тогда
ТЗ2.ДокКонца = Тз2.ПолучитьЗначение(ааа+1,"Док");

ТЗ2.ОстатокНач = 0;
ТЗ2.ОстатокПр =0;
ТЗ2.ОстатокРс =0;
ТЗ2.УдалитьСтроку(ааа+1);
Иначе
ТЗ2.ОстатокНач = 0;
ТЗ2.ОстатокПр =0;
ТЗ2.ОстатокРс =0;
ТЗ2.УдалитьСтроку(ааа);


КонецЕсли;
КонецЕсли;
КонецЦикла;

ТЗ2.выбратьСтроки();
Для ФФФ=1 по ТЗ2.КоличествоСтрок() Цикл
Попытка
ТЗ2.ПолучитьСтрокупоНомеру(ФФФ);
Исключение
Прервать;
КонецПопытки;
Если (ПустоеЗначение(ТЗ2.Док)=1) и (ПустоеЗначение(ТЗ2.ДокКонца)=1) тогда
Тз2.ЧислоДней = Число(Выбконпериода - ВыбНачПериода);
ИначеЕсли (ПустоеЗначение(ТЗ2.ДокКонца)=0) и (ПустоеЗначение(ТЗ2.Док)=0) Тогда
ТЗ2.ЧислоДней = Число(ТЗ2.ДокКонца.ДатаДок - ТЗ2.Док.ДатаДок);
ИначеЕсли (ПустоеЗначение(ТЗ2.ДокКонца)=1) и (ПустоеЗначение(ТЗ2.Док)=0) Тогда
ТЗ2.ЧислоДней = Число(ВыбКонПериода - ТЗ2.Док.ДатаДок);

ИначеЕсли (ПустоеЗначение(ТЗ2.ДокКонца)=0) и (ПустоеЗначение(ТЗ2.Док)=1) Тогда

ТЗ2.ЧислоДней = Число(ТЗ2.ДокКонца.ДатаДок - ВыбНачПериода);
КонецЕсли;
КонецЦикла;

ТЗ2.Свернуть("Товар","ЧислоДней");



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



Вот так работает. Сам накосячил - при сортировке ТЗ с документами надо указывать доп параметр - иначе он сортирует по типу а потом по дате документа.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!