Почему при получении последней цены товара в запросе 1С возникают дубли строк?

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

При разработке отчетов или обработок в 1С часто возникает задача: вывести список товаров, их обороты за период и цену последнего документа продажи. Однако при попытке объединить эти данные во временные таблицы (ВТ) многие сталкиваются с двумя проблемами: «размножением» строк (дублями) и некорректным выводом данных (например, нули вместо значений). Давайте разберемся, как решить эти задачи профессионально.

1. Почему использование МАКСИМУМ(Регистратор) — это ошибка

Первое, на что стоит обратить внимание — попытка найти «последний документ» через МАКСИМУМ(Регистратор). В платформе 1С Ссылка (регистратор) — это уникальный идентификатор, который не гарантирует хронологический порядок. Максимальный GUID не равен последней дате записи в базе. Чтобы всегда получать актуальный документ, используйте Период или МоментВремени.

2. Разбираемся с дублированием строк: Внутреннее vs Левое соединение

Дублирование строк — самая частая проблема при соединении данных. Если у вас есть таблица оборотов и таблица цен, и вы используете ВНУТРЕННЕЕ СОЕДИНЕНИЕ (Inner Join), 1С перемножает записи: если для одной номенклатуры в оборотах есть 10 записей, а в таблице цен — 1, то система будет искать соответствия, что часто приводит к логическим ошибкам или дублям.

Решение: Используйте ЛЕВОЕ СОЕДИНЕНИЕ (Left Join), чтобы сохранить все строки из основной таблицы, даже если цена еще не найдена. А чтобы избежать декартового произведения, убедитесь, что временная таблица с ценами содержит ровно одну запись на каждый товар.

3. Особенности работы виртуальной таблицы ОстаткиИОбороты

Если при попытке получить КоличествоПриход вы видите нули, хотя движения были, вероятнее всего, проблема в параметрах виртуальной таблицы. Если вы передаете Регистратор в параметры виртуальной таблицы, вы ограничиваете период действия запроса конкретной секундой этого регистратора.

Рассмотрим правильную структуру запроса:


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

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

4. Пошаговый алгоритм исправления запроса

  1. Создайте временную таблицу для цен: Отфильтруйте документы по дате и получите последнюю цену для каждой номенклатуры. Индексируйте поле Номенклатура в этой ВТ для ускорения работы.
  2. Используйте ЛЕВОЕ СОЕДИНЕНИЕ: При сборке итогового результата основной таблицей должна выступать таблица остатков/оборотов, к которой вы «пристегиваете» таблицу цен.
  3. Правильно обрабатывайте пустые значения: Функция ЕСТЬNULL сработает только в том случае, если левое соединение действительно вернуло NULL (отсутствие данных). Если поле содержит 0, ЕСТЬNULL ничего не изменит. Проверьте, нет ли у вас лишних группировок, которые превращают NULL в 0 на этапе до применения этой функции.
  4. Проверка через временные таблицы: Если данные все еще дублируются, выведите результат промежуточного запроса отдельно. Это позволит увидеть, на каком этапе «размножаются» строки.

И помните: залогом успеха в запросах 1С является разделение логики. Не пытайтесь получить все данные одним гигантским запросом, если вы не уверены в связях между таблицами. Разбейте задачу на последовательные ВТ — это упростит отладку и сделает код читаемым.

← На главную