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