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