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

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

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

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

Главная ошибка, которую допустил автор вопроса, заключается в попытке сравнить ссылку на объект базы данных с обычной строкой. Когда вы пишете в запросе ГДЕ Номенклатура.ВидНоменклатуры = &Товар, а в параметр &Товар передаете строку "Товар", система 1С не может найти соответствие. Реквизит ВидНоменклатуры имеет тип СправочникСсылка.ВидыНоменклатуры, поэтому и в параметре должна находиться ссылка на конкретный элемент этого справочника.

Шаг 1: Правильное получение ссылки на элемент

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


// Получаем ссылку на элемент справочника ВидыНоменклатуры
// Второй параметр Истина означает, что мы ищем точное соответствие по наименованию
НайденнаяСсылка = Справочники.ВидыНоменклатуры.НайтиПоНаименованию("Товары", Истина);

// Обязательно проверяем, что ссылка не пустая, прежде чем использовать ее в запросе
Если НЕ НайденнаяСсылка.Пустая() Тогда
    // Здесь будет код выполнения запроса
КонецЕсли;

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

Шаг 2: Правильная передача параметра в запрос

После того как мы получили переменную НайденнаяСсылка, содержащую ссылку на нужный вид номенклатуры, мы передаем ее в запрос с помощью метода УстановитьПараметр. Теперь тип данных в запросе (ссылка) и тип данных в параметре полностью совпадают.


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    Номенклатура.Код,
    |    Номенклатура.Наименование,
    |    Номенклатура.Артикул
    |ИЗ
    |    Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |    Номенклатура.ВидНоменклатуры = &ВидТовара";

// Передаем ссылку, а не строку!
Запрос.УстановитьПараметр("ВидТовара", НайденнаяСсылка);

Результат = Запрос.Выполнить().Выгрузить();

Почему не стоит использовать обращение к наименованию через точку?

Иногда возникает соблазн написать в тексте запроса конструкцию вида ГДЕ Номенклатура.ВидНоменклатуры.Наименование = "Товары". Не рекомендуется так делать по нескольким причинам:

  1. Производительность: Обращение через точку (разыменование ссылки) в запросе заставляет систему обращаться к таблице справочника ВидыНоменклатуры для каждой проверяемой записи, что значительно замедляет выполнение запроса.
  2. Надежность: Если наименование вида номенклатуры будет изменено пользователем, запрос перестанет работать. Ссылка на объект (GUID) остается неизменной, даже если вы переименуете элемент.

Альтернатива: использование предопределенных элементов

Если справочник ВидыНоменклатуры имеет предопределенные элементы (созданные в конфигураторе), то самый правильный и быстрый способ — обратиться к ним напрямую через менеджер справочника:


// Самый надежный способ - использование предопределенного элемента
Запрос.УстановитьПараметр("ВидТовара", Справочники.ВидыНоменклатуры.Товары);

Этот способ предпочтительнее, так как он исключает ошибки при поиске по наименованию и не зависит от того, что именно написано в поле «Наименование» в пользовательском режиме.

Итоговый алгоритм действий

  1. Всегда проверяйте типы данных: Ссылка сравнивается только со ссылкой.
  2. Если используете НайтиПоНаименованию, всегда проверяйте результат методом Пустая().
  3. В запросах избегайте лишних обращений через точку к полям объектов.
  4. Если элемент предопределенный — используйте обращение напрямую через менеджер Справочники.[ИмяСправочника].[ИмяПредопределенногоЭлемента].

Следуя этим простым правилам, вы сможете писать эффективные и надежные запросы, избегая проблем с поиском данных.

← На главную