При разработке отчетов или обработок выгрузки данных в 1С часто возникает необходимость получить актуальный остаток товара на конкретном складе и его последнюю цену. Новички, часто приходящие из 1С 7.7, склонны использовать методы перебора справочников с обращением к регистрам в цикле. Давайте разберем, почему это является ошибкой и как сделать ваш код профессиональным, быстрым и надежным.
Когда вы пишете код, в котором внутри цикла Пока Выборка.Следующий() вызываются методы ПолучитьПоследнее() для цен или Остатки() для товаров, вы создаете так называемую проблему «N+1 запросов». Для каждого элемента номенклатуры платформа вынуждена отправлять отдельный запрос к базе данных (СУБД). Если у вас в справочнике 10 000 товаров, система выполнит 20 000 отдельных транзакций. Это вызывает критическое падение производительности.
Профессиональный подход заключается в использовании механизмов ORM (Object-Relational Mapping), где все данные запрашиваются за один раз. В 1С для этого используется объект Запрос и виртуальные таблицы.
Рассмотрим, как правильно составить запрос, который за одну итерацию получит всю необходимую информацию о товарах, их ценах и остатках. Мы будем использовать ЛЕВОЕ СОЕДИНЕНИЕ, чтобы получить данные даже в том случае, если по товару нет остатка или установленной цены.
Обратите внимание на использование виртуальных таблиц ТоварыНаСкладах.Остатки и ЦеныНоменклатуры.СрезПоследних. Это позволяет платформе самостоятельно рассчитать нужные показатели на заданную дату с использованием индексов, не заставляя вас заниматься сложными математическими вычислениями вручную.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| спрНоменклатура.Ссылка КАК Ссылка,
| ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0) КАК Цена,
| ЕСТЬNULL(ТоварыНаСкладахОстатки.ВНаличииОстаток, 0) КАК Остаток
|ИЗ
| Справочник.Номенклатура КАК спрНоменклатура
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(, Склад = &Склад) КАК ТоварыНаСкладахОстатки
| ПО (ТоварыНаСкладахОстатки.Номенклатура = спрНоменклатура.Ссылка)
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, ВидЦены = &ВидЦены) КАК ЦеныНоменклатурыСрезПоследних
| ПО спрНоменклатура.Ссылка = ЦеныНоменклатурыСрезПоследних.Номенклатура
|ГДЕ
| спрНоменклатура.ЭтоГруппа = ЛОЖЬ";
Запрос.УстановитьПараметр("Склад", ВыбранныйСклад);
Запрос.УстановитьПараметр("ВидЦены", ВыбранныйВидЦены);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Здесь мы работаем с уже полученными данными без лишних обращений к базе
Сообщить("Товар: " + Выборка.Ссылка + ", Цена: " + Выборка.Цена + ", Остаток: " + Выборка.Остаток);
КонецЦикла;
ЕСТЬNULL позволяет корректно обрабатывать пустые значения (когда остаток равен 0, но запись в таблице отсутствует).Для создания сложных отчетов и выгрузок рекомендуем придерживаться следующих правил:
ДобавитьСтроку(). Используйте встроенные объекты ЗаписьXML. Это защитит ваш файл от неверных символов и проблем с кодировкой.Подводя итог, можно сказать, что 1С:Предприятие 8 — это мощная среда, эффективность которой зависит от умения разработчика правильно делегировать задачи СУБД через запросы. Переход от «семерочного» подхода к декларативному программированию с использованием запросов — это основной шаг, который превращает начинающего разработчика в профессионала.