При разработке печатных форм или отчетов часто возникает задача: вывести данные из табличной части документа (например, «Продукция») и одновременно получить связанные данные из других регистров (например, «ШтрихкодыНоменклатуры»). Начинающие разработчики часто пытаются решить это вложенным запросом прямо в списке полей выбора, что приводит к ошибкам или крайне низкой производительности. В этой статье мы разберем, как правильно построить такой запрос, как обращаться к полям шапки документа и как избежать дублирования строк, если у одного товара несколько штрихкодов.
Рассмотрим ситуацию: автор пытается получить штрихкод, используя конструкцию (ВЫБРАТЬ ШтрихкодыНоменклатуры.Штрихкод ...) внутри основного списка полей. Это называется коррелированным подзапросом. Проанализируем, почему это плохо:
Вместо вложенных запросов мы должны использовать механизм соединений. Основной таблицей в нашем случае будет выступать табличная часть документа. Разберем по шагам, как это реализовать.
Для начала выберем данные из табличной части Продукция документа ОТК_КонтрольПроволоки и присоединим к ней регистр сведений ШтрихкодыНоменклатуры. Посмотрим на базовую структуру запроса:
ВЫБРАТЬ
ТЧ_Продукция.Номенклатура,
ТЧ_Продукция.Бухта,
ТЧ_Продукция.Вес,
Штрихкоды.Штрихкод
ИЗ
Документ.ОТК_КонтрольПроволоки.Продукция КАК ТЧ_Продукция
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ШтрихкодыНоменклатуры КАК Штрихкоды
ПО ТЧ_Продукция.Номенклатура = Штрихкоды.Номенклатура
ГДЕ
ТЧ_Продукция.Ссылка = &Ссылка
Почему ЛЕВОЕ СОЕДИНЕНИЕ? Мы используем именно левое соединение, чтобы в результат попали все строки из документа, даже если для какой-то номенклатуры штрихкод еще не задан. Если использовать ВНУТРЕННЕЕ СОЕДИНЕНИЕ, строки без штрихкодов просто исчезнут из выборки.
Часто вместе с данными строк (номенклатура, количество) нужно вывести данные из «шапки» (дата документа, склад, ответственный). Выясним важный нюанс: в контексте запроса к табличной части поле Ссылка — это и есть ссылка на сам документ-владелец. Через это поле мы можем обращаться к любым реквизитам шапки, используя «точку» (разыменование ссылки).
Проанализируем пример кода, который позволяет достать дату производства и диаметр из основного документа:
ВЫБРАТЬ
ТЧ_Продукция.Ссылка.ДатаПроизводства КАК ДатаПроизводства,
ТЧ_Продукция.Ссылка.ДиаметрНоминальный КАК Диаметр,
ТЧ_Продукция.Номенклатура,
Штрихкоды.Штрихкод
ИЗ
Документ.ОТК_КонтрольПроволоки.Продукция КАК ТЧ_Продукция
...
Важный совет по оптимизации: В 1С обращение через точку в запросе (ТЧ.Ссылка.Дата) на уровне СУБД создает еще одно неявное левое соединение с таблицей документа. Если реквизитов шапки много, правильнее будет один раз явно соединиться с таблицей Документ.ОТК_КонтрольПроволоки по полю Ссылка.
Ситуация осложняется, если у одной номенклатуры в базе зарегистрировано несколько штрихкодов. В этом случае обычное соединение «размножит» строки документа: вместо одной строки с товаром вы получите столько строк, сколько штрихкодов у него найдено. Чтобы получить только один (любой или минимальный) штрихкод, применим группировку.
Рассмотрим итоговый рабочий алгоритм запроса:
ВЫБРАТЬ
ТЧ.Ссылка.ДатаПроизводства КАК ДатаПроизводства,
ТЧ.Ссылка.Катанка КАК Катанка,
ТЧ.Ссылка.ДиаметрНоминальный КАК ДиаметрНоминальный,
ТЧ.Бухта,
ТЧ.Вес,
ТЧ.Номенклатура,
МИНИМУМ(Штрихкоды.Штрихкод) КАК Штрихкод
ИЗ
Документ.ОТК_КонтрольПроволоки.Продукция КАК ТЧ
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ШтрихкодыНоменклатуры КАК Штрихкоды
ПО ТЧ.Номенклатура = Штрихкоды.Номенклатура
ГДЕ
ТЧ.Ссылка = &Ссылка
СГРУППИРОВАТЬ ПО
ТЧ.Ссылка.ДатаПроизводства,
ТЧ.Ссылка.Катанка,
ТЧ.Ссылка.ДиаметрНоминальный,
ТЧ.Бухта,
ТЧ.Вес,
ТЧ.Номенклатура
В данном примере мы используем агрегатную функцию МИНИМУМ(Штрихкод). Это гарантирует, что для каждой строки табличной части будет выбран только один штрихкод, и строки документа не будут дублироваться в печатной форме.
Чтобы ваш код был надежным и быстрым, обратите внимание на следующие моменты:
NULL. Чтобы избежать проблем при выводе, используйте функцию ЕСТЬNULL(Штрихкоды.Штрихкод, ""). Это заменит пустое значение на пустую строку.Номенклатура проиндексировано. В типовых конфигурациях это обычно так, но в самописных решениях отсутствие индекса на больших объемах данных (сотни тысяч штрихкодов) приведет к зависанию системы.Применяя эти методы, вы сможете строить гибкие и производительные запросы, которые корректно работают даже в условиях сложной структуры данных и большого количества записей в информационной базе.