Как правильно сравнивать поля и коды справочников в запросах 1С

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

При написании запросов в 1С разработчики часто сталкиваются с ситуацией, когда конструкция ВЫБОР КОГДА с условием равенства двух полей не отрабатывает так, как ожидается. На первый взгляд коды или значения совпадают, однако ветка ТОГДА пропускается, и запрос возвращает значение из ветки ИНАЧЕ. Проанализируем основные причины этой проблемы и разберем по шагам правильные способы сравнения полей в языке запросов.

Причина 1. Обращение через точку к пустому реквизиту и получение NULL

Рассмотрим частую ошибку: обращение к реквизиту ссылочного типа через точку, например ПриходныйОрдерНаТоварыТовары.Характеристика.Код. Если в строке табличной части характеристика не указана (содержит пустую ссылку), платформа 1С автоматически выполняет неявное левое соединение (LEFT JOIN) с таблицей справочника характеристик.

Так как записи в справочнике для пустой ссылки нет, результат обращения к коду возвращает значение NULL. В языке запросов 1С результат любого сравнения с NULL (например, NULL = "00001") всегда равен Ложь (неопределенность). В результате условие сравнения никогда не выполнится.

Для предотвращения этой проблемы обработаем возможные NULL с помощью функции ЕСТЬNULL:


ВЫБОР
	КОГДА ЕСТЬNULL(ПриходныйОрдерНаТоварыТовары.Характеристика.Код, "") = ЕСТЬNULL(ПриходныйОрдерНаТоварыТовары.Номенклатура.Код, "")
		ТОГДА 20
	ИНАЧЕ ПриходныйОрдерНаТоварыТовары.Количество
КОНЕЦ КАК Количество

Причина 2. Сравнение кодов из разных справочников

Выясним еще одну важную деталь: Номенклатура и ХарактеристикиНоменклатуры — это два разных справочника. Их коды генерируются независимо и почти никогда не совпадают, если логика системы не предусматривает иное.

Если задача состоит в том, чтобы проверить, принадлежит ли характеристика текущей номенклатуре, необходимо сравнивать не коды реквизитов, а подчиненность объекта через владельца:


ВЫБОР
	КОГДА ПриходныйОрдерНаТоварыТовары.Характеристика.Владелец = ПриходныйОрдерНаТоварыТовары.Номенклатура
		ТОГДА 20
	ИНАЧЕ ПриходныйОрдерНаТоварыТовары.Количество
КОНЕЦ КАК Количество

Если же требуется сравнить код номенклатуры с кодом ее владельца у характеристики, правильным условием будет:


ВЫБОР
	КОГДА ПриходныйОрдерНаТоварыТовары.Характеристика.Владелец.Код = ПриходныйОрдерНаТоварыТовары.Номенклатура.Код
		ТОГДА 20
	ИНАЧЕ ПриходныйОрдерНаТоварыТовары.Количество
КОНЕЦ КАК Количество

Причина 3. Различие типов данных и длин строк

Даже если визуально коды выглядят одинаково, причины расхождения могут заключаться в следующем:

  1. Разная длина строк в конфигураторе: Если в одном справочнике длина кода равна 9 символам, а в другом — 11, СУБД дополняет более короткую строку пробелами справа. В результате прямое сравнение строк разной длины вернет Ложь. Чтобы привести строки к одной длине, используем функцию ВЫРАЗИТЬ.
  2. Несовпадение типов: В одном справочнике код может быть числовым, а в другом — строковым. В языке запросов 1С сравнение числа со строкой всегда возвращает Ложь.

Пример применения функции ВЫРАЗИТЬ для явного приведения длины строки:


ВЫБОР
	КОГДА ВЫРАЗИТЬ(ПриходныйОрдерНаТоварыТовары.Характеристика.Код КАК СТРОКА(10)) = ВЫРАЗИТЬ(ПриходныйОрдерНаТоварыТовары.Номенклатура.Код КАК СТРОКА(10))
		ТОГДА 20
	ИНАЧЕ ПриходныйОрдерНаТоварыТовары.Количество
КОНЕЦ КАК Количество

Причина 4. Сравнение значений из разных строк табличной части

Если требуется сравнить значения не в рамках одной строки табличной части, а сопоставить каждую строку со всеми остальными строками документа, обычное выражение ВЫБОР КОГДА в одном запросе не сработает, так как запрос обрабатывает записи построчно.

В этом случае проанализируем архитектуру запроса и задействуем временные таблицы:

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

Использование временных таблиц позволяет нормализовать исходные данные, заранее заменить NULL на значения по умолчанию и выполнить корректные соединения перед проверкой условий.

← На главную