Как правильно выбрать данные из нескольких табличных частей документа в запросе 1С?

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

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

Разбор причины ошибки: Декартово произведение

Основная ошибка заключается в том, как таблицы указываются в операторе ВЫБРАТЬ ... ИЗ. Если вы перечисляете несколько таблиц через запятую, например:


ВЫБРАТЬ
    Товары.Номенклатура,
    Серии.СерийныйНомер
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК Товары,
    Документ.РеализацияТоваровУслуг.СерийныеНомера КАК Серии

Система выполняет так называемое декартово произведение. Это означает, что каждая строка из первой таблицы сопоставляется с каждой строкой из второй. В результате, если в документе 10 товаров и 5 серийных номеров, вы получите 50 строк. Это логически неверный результат для заполнения табличной части документа.

Решение: Использование соединения таблиц

Чтобы данные из разных табличных частей соответствовали друг другу, необходимо использовать механизмы соединения. Наиболее универсальным является ЛЕВОЕ СОЕДИНЕНИЕ. Оно позволяет получить все данные из основной таблицы (например, Товары), даже если для них нет соответствующих записей в таблице Серии.

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


ВЫБРАТЬ
    Товары.НомерСтроки КАК НомерСтроки,
    Товары.Номенклатура КАК Номенклатура,
    Товары.Количество КАК Количество,
    Серии.СерийныйНомер КАК СерийныйНомер
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ 
    Документ.РеализацияТоваровУслуг.СерийныеНомера КАК Серии
ПО 
    Товары.Ссылка = Серии.Ссылка 
    И Товары.НомерСтроки = Серии.НомерСтроки
ГДЕ 
    Товары.Ссылка = &Ссылка

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

  1. Использование псевдонимов (Алиасов): Всегда используйте ключевое слово КАК для именования полей. Это делает обращение к полям в коде 1С через конструкцию ВыборкаДетальныеЗаписи.ИмяПоля предсказуемым. Без КАК система может присвоить полям сложные системные имена, что приведет к ошибкам при обращении.
  2. Связь по строкам: Для корректной связи используйте не только Ссылка, но и НомерСтроки (или КлючСтроки в современных конфигурациях). Это гарантирует, что серийный номер попадет именно в ту строку товара, к которой он относится.
  3. Оптимизация обращения к ссылкам: Помните, что обращение СерийныйНомер.Ссылка в цикле вызывает «разыменование» — дополнительный запрос к базе данных для каждой строки. Старайтесь вытаскивать нужные реквизиты (Наименование, Код) сразу в тексте запроса через точку: СерийныйНомер.Код КАК КодСерийногоНомера.
  4. Проверка типов данных: При обращении к полю в цикле убедитесь, что вы обращаетесь к правильному псевдониму, который задали в секции ВЫБРАТЬ.

Разберем пример заполнения табличной части в коде 1С:


Функция ЗаполнениеТаблицы(докрел)
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ ... (текст запроса с соединением)";
    Запрос.УстановитьПараметр("Ссылка", докрел);
    
    Результат = Запрос.Выполнить();
    Выборка = Результат.Выбрать();
    
    Товары.Очистить();
    Пока Выборка.Следующий() Цикл
        Стр = Товары.Добавить();
        Стр.Наименование = Выборка.Номенклатура;
        Стр.Количество = Выборка.Количество;
        Стр.СерийныйНомер = Выборка.СерийныйНомер;
    КонецЦикла;
КонецФункции

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

← На главную