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