Отбор данных в языке запросов 1С 8.3: какие условия бывают и где их писать

· 9 мин

Содержание

Условие в запросе 1С ставят в секции ГДЕ после ИЗ: ГДЕ Документ.Проведен = ИСТИНА И Документ.Дата МЕЖДУ &Начало И &Конец. Значения из кода передают параметрами через Запрос.УстановитьПараметр("Начало", НачалоДня(ДатаНачала)), а не вклеивают в текст. В конструкторе запроса то же самое делается на вкладке «Условия».

Типичная ситуация: отчёт по реализации показывает все документы подряд, включая непроведённые и помеченные на удаление. Нужно отсечь лишнее, оставить один период и одного контрагента. Ниже — синтаксис условий языка запросов 1С 8.3 с примерами, от простого фильтра до подзапросов. Язык запросов общий для платформы, поэтому всё работает в любой конфигурации: БП 3.0, ЗУП 3.1, УТ 11 и своих разработках. Имена объектов в примерах взяты из Бухгалтерии предприятия.

Секция ГДЕ и операторы сравнения

Минимальный запрос с условием выглядит так:

ВЫБРАТЬ
	Реализация.Ссылка,
	Реализация.Дата,
	Реализация.СуммаДокумента
ИЗ
	Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
	Реализация.Проведен
	И НЕ Реализация.ПометкаУдаления
	И Реализация.СуммаДокумента > 10000

Булево поле можно писать без = ИСТИНА: ГДЕ Реализация.Проведен читается так же. Секция ГДЕ стоит после ИЗ и соединений, но перед СГРУППИРОВАТЬ ПО и УПОРЯДОЧИТЬ ПО.

Какие операторы доступны:

ОператорЧто проверяетПример
=, <>равно / не равноСклад = &Склад
>, <, >=, <=больше / меньшеКоличество >= 5
МЕЖДУ … И …диапазон включительноДата МЕЖДУ &Начало И &Конец
В (…)значение из спискаСклад В (&Склады)
В ИЕРАРХИИ (…)элемент или любой его потомокНоменклатура В ИЕРАРХИИ (&Группа)
ПОДОБНОстрока по шаблонуНаименование ПОДОБНО "%кабель%"
ЕСТЬ NULLполе не заполнено соединениемОстатки.Количество ЕСТЬ NULL
ССЫЛКАтип ссылки в составном полеРегистратор ССЫЛКА Документ.РеализацияТоваровУслуг

Шаблоны для ПОДОБНО

  • 🔹 % — любое количество любых символов, в том числе ноль;
  • 🔹 _ — ровно один любой символ;
  • 🔹 [а-в] — один символ из диапазона, [^0-9] — любой, кроме цифры.

Если сам символ % или _ нужно искать буквально, добавьте СПЕЦСИМВОЛ: Артикул ПОДОБНО "%!_%" СПЕЦСИМВОЛ "!" найдёт артикулы с подчёркиванием.

Шаблон для ПОДОБНО тоже удобно передавать параметром. Склейте его в коде: Запрос.УстановитьПараметр("Шаблон", "%" + СтрокаПоиска + "%"), а в тексте оставьте ПОДОБНО &Шаблон.

Условие через конструктор запроса

Если текст писать не хочется, откройте конструктор (в модуле — правой кнопкой по тексту запроса или через меню Текст → Конструктор запроса). Порядок такой:

  1. На вкладке «Таблицы и поля» выберите таблицу и поля.
  2. Перейдите на вкладку «Условия».
  3. Перетащите поле из левого списка в правый — конструктор сам подставит условие вида Поле = &Поле и создаст параметр.
  4. Чтобы написать выражение вручную (с ИЛИ, ПОДОБНО, функциями), включите флажок «Произвольное» в строке условия.

Строки на вкладке «Условия» конструктор соединяет через И. Для ИЛИ нужна одна произвольная строка со скобками.

Как связать несколько условий: И, ИЛИ, НЕ

Логические операторы работают по приоритету: сначала НЕ, затем И, последним ИЛИ. Из-за этого запрос без скобок часто возвращает не то, что задумано.

Задача: проведённые документы, у которых контрагент — Альфа или Бета. Неверный вариант:

ГДЕ
	Реализация.Проведен
	И Реализация.Контрагент = &Альфа
	ИЛИ Реализация.Контрагент = &Бета

Платформа прочитает это как «(проведён И Альфа) ИЛИ Бета». В выборку попадут непроведённые документы по Бете. Правильно — скобки:

ГДЕ
	Реализация.Проведен
	И (Реализация.Контрагент = &Альфа
		ИЛИ Реализация.Контрагент = &Бета)

А ещё лучше — заменить цепочку ИЛИ по одному полю на В: Реализация.Контрагент В (&Альфа, &Бета). Короче, читается легче и не ломается при добавлении нового условия.

НЕ ставится перед любым выражением: НЕ Склад В (&Склады), НЕ Наименование ПОДОБНО "Архив%", НЕ Поле ЕСТЬ NULL (допустимо и Поле ЕСТЬ НЕ NULL).

Если в условии есть и И, и ИЛИ, всегда ставьте скобки, даже если приоритет вас устраивает. Через полгода коллега добавит строчку — и логика тихо поменяется.

Параметры в условиях запроса

Параметр в тексте обозначается амперсандом: &Контрагент. Значение задаётся до выполнения:

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
|	Реализация.Ссылка
|ИЗ
|	Документ.РеализацияТоваровУслуг КАК Реализация
|ГДЕ
|	Реализация.Контрагент = &Контрагент
|	И Реализация.Организация В (&Организации)";

Запрос.УстановитьПараметр("Контрагент", Контрагент);
Запрос.УстановитьПараметр("Организации", МассивОрганизаций);

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
	Сообщить(Выборка.Ссылка);
КонецЦикла;

Почему параметр лучше, чем склейка строки вида "... = """ + Значение + """":

  • ✅ ссылку на объект вообще нельзя вклеить в текст — только передать параметром;
  • ✅ не нужно возиться с кавычками и форматом дат;
  • ✅ один и тот же текст запроса работает с разными значениями.

Список значений и иерархия

Для оператора В (&Список) передайте Массив, СписокЗначений или колонку таблицы значений, выгруженную в массив через ВыгрузитьКолонку(). Пустой массив не ошибка: условие просто не найдёт ни одной строки.

В ИЕРАРХИИ нужен для иерархических справочников. Условие Номенклатура В ИЕРАРХИИ (&ГруппаКабели) вернёт и саму группу, и все вложенные подгруппы и элементы. Обычное Номенклатура.Родитель = &ГруппаКабели возьмёт только первый уровень.

Необязательный отбор

Частая задача: если пользователь выбрал склад — фильтровать по нему, если нет — показывать все. Вариант с флагом:

ГДЕ
	(&БезОтбораПоСкладу ИЛИ Остатки.Склад = &Склад)

В коде: Запрос.УстановитьПараметр("БезОтбораПоСкладу", НЕ ЗначениеЗаполнено(Склад)). Для больших таблиц быстрее собрать текст условия в коде и добавлять строку И Склад = &Склад только при заполненном отборе: так СУБД получает простое условие и может использовать индекс.

Отбор по датам и периодам

Поле Дата у документа хранит дату и время. Поэтому Дата = &День почти никогда ничего не находит: документ проведён в 14:35, а параметр — 00:00:00.

Правильный отбор за период:

ГДЕ
	Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(ДатаС));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(ДатаПо));

Если граница приходит из поля выбора даты без времени, без КонецДня() документы последнего дня выпадут из отчёта. Это самая частая причина «не сходится на одну дату».

Функции периода есть и внутри самого языка запросов:

ЗадачаВыражение в запросе
Дата-константаДАТАВРЕМЯ(2025, 1, 1)
Начало месяца от поляНАЧАЛОПЕРИОДА(Реализация.Дата, МЕСЯЦ)
Конец квартала от параметраКОНЕЦПЕРИОДА(&Дата, КВАРТАЛ)
Сдвиг на 30 дней назадДОБАВИТЬКДАТЕ(&Дата, ДЕНЬ, -30)
Разница в дняхРАЗНОСТЬДАТ(Реализация.Дата, &Дата, ДЕНЬ)
Отбор по годуГОД(Реализация.Дата) = 2025

Условие ГОД(Дата) = 2025 работает, но оборачивание поля функцией мешает СУБД использовать индекс по дате. На больших базах пишите диапазоном: Дата МЕЖДУ ДАТАВРЕМЯ(2025, 1, 1) И ДАТАВРЕМЯ(2025, 12, 31, 23, 59, 59).

Для виртуальных таблиц регистров (Остатки, Обороты, ОстаткиИОбороты) период задают не в ГДЕ, а первыми параметрами самой таблицы. Об этом — в разделе про сложные условия.

Ссылки, пустые значения и NULL

Здесь три разные сущности, и путать их нельзя.

Пустая ссылка — реквизит есть, но не заполнен. Сравнивают с предопределённым значением через ЗНАЧЕНИЕ():

ГДЕ
	Реализация.Договор = ЗНАЧЕНИЕ(Справочник.ДоговорыКонтрагентов.ПустаяСсылка)

Через ЗНАЧЕНИЕ() в текст запроса подставляют и другие известные заранее значения: элементы перечислений, предопределённые элементы справочников и счета. Например, ЗНАЧЕНИЕ(Перечисление.ЮридическоеФизическоеЛицо.ЮридическоеЛицо) или ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.Касса). Параметр для таких констант заводить не нужно.

Пустая дата — ДАТАВРЕМЯ(1, 1, 1). Пустая строка — "". Пустое число — 0.

NULL — значения нет вообще. Он появляется, когда при левом соединении справа не нашлось пары, или когда поле разыменовывается через ссылку другого типа. Сравнение = NULL не работает , нужен оператор ЕСТЬ NULL:

ВЫБРАТЬ
	Номенклатура.Ссылка
ИЗ
	Справочник.Номенклатура КАК Номенклатура
		ЛЕВОЕ СОЕДИНЕНИЕ ЦеныТоваров КАК Цены
		ПО Номенклатура.Ссылка = Цены.Номенклатура
ГДЕ
	Цены.Цена ЕСТЬ NULL

Так находят товары, для которых нет цены (здесь ЦеныТоваров — временная таблица, подготовленная выше). Чтобы превратить NULL в ноль для расчётов, есть функция ЕСТЬNULL(Цены.Цена, 0).

Проверка «поле не заполнено» для реквизита, который может быть и пустой ссылкой, и NULL (например, после соединения): ЕСТЬNULL(Поле, ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)) = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка).

Составной тип и оператор ССЫЛКА

У регистров поле Регистратор может ссылаться на документы разных видов. Чтобы оставить только реализации, пишут Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг. Функция ТИПЗНАЧЕНИЯ(Поле) = ТИП(Документ.РеализацияТоваровУслуг) даёт тот же результат, но ССЫЛКА короче.

Сложные условия: подзапросы, временные таблицы, соединения

Условие с подзапросом

Оператор В принимает не только список, но и вложенный запрос:

ГДЕ
	Контрагенты.Ссылка В
		(ВЫБРАТЬ
			Реализация.Контрагент
		ИЗ
			Документ.РеализацияТоваровУслуг КАК Реализация
		ГДЕ
			Реализация.Проведен
			И Реализация.Дата >= &Начало)

Получатся контрагенты, которым была хотя бы одна отгрузка с указанной даты. НЕ В (ВЫБРАТЬ …) — наоборот, те, кому отгрузок не было.

Временная таблица вместо тяжёлого подзапроса

Если подзапрос большой или нужен дважды, вынесите его во временную таблицу в пакете запросов:

ВЫБРАТЬ РАЗЛИЧНЫЕ
	Реализация.Контрагент КАК Контрагент
ПОМЕСТИТЬ ВТ_Покупатели
ИЗ
	Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
	Реализация.Проведен
	И Реализация.Дата МЕЖДУ &Начало И &Конец
ИНДЕКСИРОВАТЬ ПО
	Контрагент
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	Контрагенты.Ссылка
ИЗ
	Справочник.Контрагенты КАК Контрагенты
ГДЕ
	Контрагенты.Ссылка В
		(ВЫБРАТЬ ВТ.Контрагент ИЗ ВТ_Покупатели КАК ВТ)

Пакетные запросы разделяются точкой с запятой; строка из слэшей — просто комментарий, который вставляет конструктор. Временные таблицы живут, пока существует менеджер временных таблиц запроса.

Условие внутри параметров виртуальной таблицы

Это главный приём оптимизации, который знает каждый разработчик 1С. Отбор для Остатки и Обороты пишут в скобках самой таблицы:

ВЫБРАТЬ
	Остатки.Субконто1,
	Остатки.СуммаОстаток
ИЗ
	РегистрБухгалтерии.Хозрасчетный.Остатки(
		&Дата,
		Счет В ИЕРАРХИИ (ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.РасчетыСПокупателями)),
		,
		Организация = &Организация) КАК Остатки

Если перенести Организация = &Организация в ГДЕ, результат будет тем же, но платформа сначала посчитает остатки по всем организациям и только потом отбросит лишнее. В параметре отбор срабатывает до расчёта — на большой базе разница бывает в разы.

Условие соединения и ИМЕЮЩИЕ

  • 🔸 Условие в ПО при левом соединении фильтрует только правую таблицу, строки левой остаются. То же условие в ГДЕ отсечёт строки, где справа NULL, и левое соединение фактически станет внутренним.
  • 🔸 ИМЕЮЩИЕ — условие на итог группировки. ГДЕ отбирает строки до группировки, ИМЕЮЩИЕ — группы после: СГРУППИРОВАТЬ ПО Контрагент ИМЕЮЩИЕ СУММА(СуммаДокумента) > 100000.
  • 🔸 ВЫБОР допустим и в условии: ГДЕ ВЫБОР КОГДА &ТолькоКрупные ТОГДА СуммаДокумента > 100000 ИНАЧЕ ИСТИНА КОНЕЦ.

Почему условие не срабатывает или тормозит

Диагностика: выберите симптом

Ещё две вещи, которые не дают ошибки, но портят результат:

  1. Разыменование через точку в условии. ГДЕ Реализация.Контрагент.ИНН = &ИНН выглядит невинно, но платформа неявно подключает таблицу контрагентов. Если поле составного типа, соединений будет по одному на каждый тип. Для отбора по реквизиту лучше сначала найти ссылку на контрагента, а в запрос передать её.
  2. Условие на поле, которого нет у части строк. В объединённых запросах каждое ОБЪЕДИНИТЬ имеет свою секцию ГДЕ. Условие из первой части на вторую не распространяется.

Проверять запросы удобно в консоли запросов (обработка входит в набор инструментов разработчика или в состав некоторых конфигураций): туда вставляют текст, заполняют параметры и сразу видят результат и время выполнения.

Частые вопросы

Можно ли использовать в условии поле, которого нет в ВЫБРАТЬ?
Да. Секция ГДЕ работает с любыми полями источников из ИЗ, выводить их в результат не обязательно.
Как отобрать документы нескольких видов из журнала или регистра?
Перечислите типы через ИЛИ в скобках: (Регистратор ССЫЛКА Документ.А ИЛИ Регистратор ССЫЛКА Документ.Б).
Чем отличается условие в запросе от отбора в СКД?
Отбор схемы компоновки пользователь меняет в настройках отчёта без правки кода. Жёсткое условие в тексте запроса действует всегда. В СКД поля в фигурных скобках {} позволяют платформе самой встроить отбор в нужное место запроса.
Как найти записи, у которых строка начинается с цифры?
Через ПОДОБНО с диапазоном: Наименование ПОДОБНО “[0-9]%”.
Учитывается ли пометка удаления автоматически?
Нет. Помеченные на удаление объекты попадают в выборку, пока вы явно не добавите условие НЕ ПометкаУдаления.