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