Как правильно получать остатки товаров и цены в 1С:Управление торговлей 11?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

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

Почему стоит избегать обращения к регистрам в цикле

Когда вы пишете код, в котором внутри цикла Пока Выборка.Следующий() вызываются методы ПолучитьПоследнее() для цен или Остатки() для товаров, вы создаете так называемую проблему «N+1 запросов». Для каждого элемента номенклатуры платформа вынуждена отправлять отдельный запрос к базе данных (СУБД). Если у вас в справочнике 10 000 товаров, система выполнит 20 000 отдельных транзакций. Это вызывает критическое падение производительности.

Профессиональный подход заключается в использовании механизмов ORM (Object-Relational Mapping), где все данные запрашиваются за один раз. В 1С для этого используется объект Запрос и виртуальные таблицы.

Решение с использованием единого запроса

Рассмотрим, как правильно составить запрос, который за одну итерацию получит всю необходимую информацию о товарах, их ценах и остатках. Мы будем использовать ЛЕВОЕ СОЕДИНЕНИЕ, чтобы получить данные даже в том случае, если по товару нет остатка или установленной цены.

Обратите внимание на использование виртуальных таблиц ТоварыНаСкладах.Остатки и ЦеныНоменклатуры.СрезПоследних. Это позволяет платформе самостоятельно рассчитать нужные показатели на заданную дату с использованием индексов, не заставляя вас заниматься сложными математическими вычислениями вручную.


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    спрНоменклатура.Ссылка КАК Ссылка,
    |    ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0) КАК Цена,
    |    ЕСТЬNULL(ТоварыНаСкладахОстатки.ВНаличииОстаток, 0) КАК Остаток
    |ИЗ
    |    Справочник.Номенклатура КАК спрНоменклатура
    |    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(, Склад = &Склад) КАК ТоварыНаСкладахОстатки
    |    ПО (ТоварыНаСкладахОстатки.Номенклатура = спрНоменклатура.Ссылка)
    |    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, ВидЦены = &ВидЦены) КАК ЦеныНоменклатурыСрезПоследних
    |    ПО спрНоменклатура.Ссылка = ЦеныНоменклатурыСрезПоследних.Номенклатура
    |ГДЕ
    |    спрНоменклатура.ЭтоГруппа = ЛОЖЬ";

Запрос.УстановитьПараметр("Склад", ВыбранныйСклад);
Запрос.УстановитьПараметр("ВидЦены", ВыбранныйВидЦены);

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    // Здесь мы работаем с уже полученными данными без лишних обращений к базе
    Сообщить("Товар: " + Выборка.Ссылка + ", Цена: " + Выборка.Цена + ", Остаток: " + Выборка.Остаток);
КонецЦикла;

Преимущества данного метода

  1. Скорость работы: Выполнение одного тяжелого запроса всегда быстрее, чем тысячи мелких обращений к СУБД.
  2. Корректность данных: Использование ЕСТЬNULL позволяет корректно обрабатывать пустые значения (когда остаток равен 0, но запись в таблице отсутствует).
  3. Читаемость: Код становится декларативным — вы описываете, что хотите получить, а не как именно системе перебирать записи.

Важные рекомендации для разработки

Для создания сложных отчетов и выгрузок рекомендуем придерживаться следующих правил:

Подводя итог, можно сказать, что 1С:Предприятие 8 — это мощная среда, эффективность которой зависит от умения разработчика правильно делегировать задачи СУБД через запросы. Переход от «семерочного» подхода к декларативному программированию с использованием запросов — это основной шаг, который превращает начинающего разработчика в профессионала.

← На главную