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