Как объединить остатки товаров и цены из прайс-листа в одном запросе 1С?

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

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

Разберем типичные ошибки и выберем правильный подход

Проанализируем ситуацию: начинающие разработчики часто пытаются обращаться к физическим таблицам регистров, таким как РегистрНакопления.ТоварыНаСкладах или РегистрСведений.ЦеныНоменклатуры. Рассмотрим, почему это неверно:

Шаг 1: Получение остатков во временную таблицу

Первым делом нам необходимо получить актуальные остатки товаров. Для этого мы обратимся к виртуальной таблице Остатки. Чтобы запрос работал быстро, мы поместим результат во временную таблицу и проиндексируем её по полю Номенклатура. Проанализируем пример кода:


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

В этом фрагменте мы используем &Период для получения остатков на конкретный момент времени. Инструкция ИНДЕКСИРОВАТЬ ПО крайне важна: она создает индекс во временной таблице, что позволит платформе мгновенно выполнить соединение с таблицей цен на следующем этапе.

Шаг 2: Получение цен через СрезПоследних

Цены в 1С хранятся в периодических регистрах сведений. Чтобы получить самую свежую цену на дату отчета, используется виртуальная таблица СрезПоследних. Рассмотрим, как правильно настроить параметры этой таблицы:


ВЫБРАТЬ
    ЦеныНоменклатурыСрезПоследних.Номенклатура КАК Номенклатура,
    ЦеныНоменклатурыСрезПоследних.Цена КАК Цена,
    ЦеныНоменклатурыСрезПоследних.Валюта КАК Валюта
ПОМЕСТИТЬ ВТ_Цены
ИЗ
    РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ВидЦены = &НужныйВидЦены) КАК ЦеныНоменклатурыСрезПоследних
ИНДЕКСИРОВАТЬ ПО
    Номенклатура
;

Обратите внимание: мы передаем ВидЦены непосредственно в параметры виртуальной таблицы. Это критически важно, чтобы не получить "кашу" из всех возможных типов цен, существующих в базе.

Шаг 3: Объединение данных (Левое соединение)

Теперь, когда у нас есть две подготовленные временные таблицы, мы должны их соединить. Выясним причину, по которой здесь используется именно ЛЕВОЕ СОЕДИНЕНИЕ: нам важно увидеть все товары, которые есть на остатке, даже если для них по какой-то причине не задана цена в прайс-листе. Если использовать ВНУТРЕННЕЕ СОЕДИНЕНИЕ, товары без цен просто исчезнут из результата.

Также важно предусмотреть обработку пустых значений. Если цены нет, запрос вернет NULL. Чтобы в колонке "Цена" стоял красивый "0", используем функцию ЕСТЬNULL.


ВЫБРАТЬ
    ВТ_Остатки.Номенклатура КАК Товар,
    ВТ_Остатки.Склад КАК Склад,
    ВТ_Остатки.Остаток КАК Количество,
    ЕСТЬNULL(ВТ_Цены.Цена, 0) КАК Цена,
    ЕСТЬNULL(ВТ_Остатки.Остаток * ВТ_Цены.Цена, 0) КАК СуммаВЦенных
ИЗ
    ВТ_Остатки КАК ВТ_Остатки
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Цены КАК ВТ_Цены
        ПО ВТ_Остатки.Номенклатура = ВТ_Цены.Номенклатура

Дополнительные рекомендации для профессиональной разработки

Рассмотрим еще несколько важных моментов, которые помогут сделать ваш запрос идеальным:

  1. Учет характеристик: Если в вашей программе ведется учет по характеристикам (размеры, цвета), то соединение нужно делать не только по полю Номенклатура, но и по полю Характеристика. В противном случае цена может установиться неверно.
  2. Момент времени: Для получения максимально точных остатков на текущую секунду, в параметр &Период рекомендуется передавать объект Граница или МоментВремени, чтобы включить движения документов, записанных в ту же секунду.
  3. Использование Консоли запросов: Перед тем как вставлять код в конфигуратор, обязательно проверьте его в "Консоли запросов". Это позволит вам увидеть промежуточные результаты временных таблиц и убедиться в отсутствии дублей.

Проанализировав вышеописанный подход, мы видим, что разделение запроса на получение остатков и получение цен через временные таблицы — это наиболее стабильный и производительный метод. Он позволяет легко масштабировать запрос (например, добавить расчет резервов или цен в разных валютах), сохраняя при этом читаемость кода и высокую скорость выполнения на сервере.

← На главную