Как отбирать записи в языке запросов 1С: всё про секцию ГДЕ
Содержание
Условие ГДЕ в запросе 1С отбирает строки до группировки: пишется после ИЗ и всех соединений, но перед СГРУППИРОВАТЬ ПО. Простейший пример — ГДЕ Документ.Проведен И Документ.Дата МЕЖДУ &НачалоПериода И &КонецПериода. Всё, что сравнивается со значениями извне, передавайте параметрами через &, а не склеивайте в текст запроса.
Синтаксис одинаков для всей платформы 8.3 и не зависит от конфигурации: в Бухгалтерии, ЗУП и УТ условия пишутся одними и теми же операторами. Разница только в именах таблиц и реквизитов.
Где стоит ГДЕ в тексте запроса и как записать условие
Порядок секций в запросе жёсткий. Перепутаете — получите синтаксическую ошибку при выполнении.
ВЫБРАТЬ
Реализация.Ссылка,
Реализация.Контрагент,
Реализация.СуммаДокумента
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
Реализация.Проведен
И Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода
И Реализация.СуммаДокумента > 100000
УПОРЯДОЧИТЬ ПО
Реализация.Дата
Полный порядок такой: ВЫБРАТЬ → ПОМЕСТИТЬ → ИЗ → соединения → ГДЕ → СГРУППИРОВАТЬ ПО → ИМЕЮЩИЕ → УПОРЯДОЧИТЬ ПО → ИТОГИ.
Что нужно знать о самом условии:
- 🔹 Логическое поле можно писать без сравнения:
ГДЕ Реализация.Проведенравносильно= ИСТИНА, аГДЕ НЕ Реализация.ПометкаУдаления— отбор неудалённых. - 🔹 Условия соединяются через
И,ИЛИ,НЕ. Приоритет: сначалаНЕ, потомИ, потомИЛИ. СмешиваетеИсИЛИ— ставьте скобки. - 🔹 Псевдоним поля из
ВЫБРАТЬвГДЕиспользовать нельзя. Повторите выражение целиком. - 🔹 Агрегатные функции (
СУММА,КОЛИЧЕСТВО) вГДЕнедопустимы — для отбора по итогам естьИМЕЮЩИЕ.
Параметры задаются в коде перед выполнением:
Запрос = Новый Запрос;
Запрос.Текст = ТекстЗапроса;
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(ДатаНачала));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(ДатаОкончания));
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Контрагент);
КонецЦикла;
В конструкторе запроса условия собираются на вкладке «Условия». Перетащите поле в правую часть — конструктор сам предложит параметр. Для выражения сложнее простого сравнения поставьте флажок «Произвольное» и напишите условие текстом.
ГДЕ или ИМЕЮЩИЕ
| Что отбираем | Секция | Пример |
|---|---|---|
| Строки исходной таблицы | ГДЕ | ГДЕ Продажи.Склад = &Склад |
| Группы по итогу | ИМЕЮЩИЕ | ИМЕЮЩИЕ СУММА(Продажи.Сумма) > 50000 |
| И то и другое | обе | сначала ГДЕ, затем ИМЕЮЩИЕ |
Чем больше строк отсечёт ГДЕ, тем меньше работы у группировки. Поэтому условие на исходные поля в ИМЕЮЩИЕ не переносите.
Операторы условия ГДЕ: сравнение, списки, иерархия, типы
Базовое сравнение — =, <>, <, >, <=, >=. Остальные операторы закрывают типовые задачи отбора.
| Оператор | Что делает | Пример |
|---|---|---|
МЕЖДУ … И … | Диапазон, обе границы включаются | Дата МЕЖДУ &Начало И &Конец |
В (…) | Значение входит в список | Склад В (&СписокСкладов) |
В ИЕРАРХИИ (…) | Элемент или любой потомок группы | Номенклатура В ИЕРАРХИИ (&Группа) |
ПОДОБНО | Отбор по шаблону строки | Наименование ПОДОБНО "%болт%" |
ЕСТЬ NULL | Значение отсутствует | Остатки.Количество ЕСТЬ NULL |
ССЫЛКА | Ссылка нужного типа в составном поле | Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг |
Списки значений
В параметр для оператора В передают массив или список значений. Для пары-тройки фиксированных значений подойдёт и литерал:
ГДЕ
Контрагенты.ЮридическоеФизическоеЛицо В (
ЗНАЧЕНИЕ(Перечисление.ЮридическоеФизическоеЛицо.ЮридическоеЛицо),
ЗНАЧЕНИЕ(Перечисление.ЮридическоеФизическоеЛицо.ФизическоеЛицо))
Функция ЗНАЧЕНИЕ() позволяет вписать предопределённое значение, значение перечисления или пустую ссылку прямо в текст запроса без параметра.
💡 Отрицание пишется как НЕ Склад В (&Склады). Если список пустой, В не отберёт ничего, а НЕ … В отберёт всё. Проверяйте пустоту списка в коде до запуска, иначе отчёт молча покажет либо ноль, либо всю базу.
Отбор по типу составного поля
У регистраторов, субконто и реквизитов составного типа удобно ограничивать тип значения:
ГДЕ
Движения.Регистратор ССЫЛКА Документ.ПоступлениеТоваровУслуг
ИЛИ Движения.Регистратор ССЫЛКА Документ.ВозвратТоваровОтКлиента
Альтернатива — ТИПЗНАЧЕНИЯ(Поле) = ТИП(Документ.ПоступлениеТоваровУслуг). Результат тот же, ССЫЛКА короче. Имена документов в примерах взяты из типовых конфигураций — в вашей базе сверяйте их по дереву метаданных или через конструктор.
Даты и строки в условиях запроса
Отбор по датам
Главная ловушка — время в дате. Документ от 31 марта 15:40 не попадёт в отбор Дата <= &Конец, если в параметр передали 31 марта 00:00:00. Решений два:
- Передавать конец периода через
КонецДня()в коде, как в примере выше. - Округлять внутри запроса:
МЕЖДУ НАЧАЛОПЕРИОДА(&Начало, ДЕНЬ) И КОНЕЦПЕРИОДА(&Конец, ДЕНЬ).
Полезные функции работы с датой в языке запросов:
- 📅
ДАТАВРЕМЯ(2025, 1, 1)— дата-литерал;ДАТАВРЕМЯ(1, 1, 1)— пустая дата. - 📅
НАЧАЛОПЕРИОДА(Дата, МЕСЯЦ)иКОНЕЦПЕРИОДА(Дата, КВАРТАЛ)— границы периода. - 📅
ДОБАВИТЬКДАТЕ(&Дата, ДЕНЬ, -30)— сдвиг даты. - 📅
РАЗНОСТЬДАТ(Документ.Дата, &ТекущаяДата, ДЕНЬ)— разница в днях.
Пример: счета старше 30 дней от даты отчёта.
ГДЕ
РАЗНОСТЬДАТ(Счет.Дата, &ДатаОтчета, ДЕНЬ) > 30
Этот вариант читается легко, но индекс по дате он не использует. На больших таблицах лучше Счет.Дата < ДОБАВИТЬКДАТЕ(&ДатаОтчета, ДЕНЬ, -30) — функция применяется к параметру, а поле остаётся «чистым».
Отбор по строкам: ПОДОБНО
ПОДОБНО сравнивает строку с шаблоном. Спецсимволы шаблона:
| Символ | Значение |
|---|---|
% | Любое количество любых символов, в том числе ноль |
_ | Ровно один любой символ |
[абв] | Один символ из перечисленных |
[а-я] | Один символ из диапазона |
[^0-9] | Один символ, не входящий в диапазон |
Поиск подстроки, введённой пользователем:
ГДЕ
Номенклатура.Наименование ПОДОБНО &Шаблон СПЕЦСИМВОЛ "~"
В коде шаблон собирают так: "%" + СтрЗаменить(Строка, "%", "~%") + "%". Если пользователь ввёл 50%, без экранирования знак процента сработает как шаблон и отбор станет шире. По-хорошему экранируют и _, и квадратные скобки.
⚠️ Строки неограниченной длины (реквизиты вроде «Комментарий» с длиной 0) напрямую сравнивать через = нельзя — запрос упадёт. Приведите поле к строке фиксированной длины: ВЫРАЗИТЬ(Документ.Комментарий КАК СТРОКА(200)) = &Текст.
NULL, пустые ссылки и пустые значения
В 1С это три разные вещи, и путают их постоянно.
- ⚪ NULL — значения нет вообще. Появляется в левом соединении, когда справа не нашлось пары, и в составных полях, если реквизит не относится к данному типу.
- ⚪ Пустая ссылка — значение есть, но ссылка ни на что не указывает. Например, документ без заполненного контрагента.
- ⚪ НЕОПРЕДЕЛЕНО — пустое значение в реквизите составного типа, пока тип не выбран.
Как проверять:
// Значения нет совсем
ГДЕ Остатки.КоличествоОстаток ЕСТЬ NULL
// Контрагент не заполнен
ГДЕ Реализация.Контрагент = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)
// Пустая дата
ГДЕ Документ.ДатаОплаты = ДАТАВРЕМЯ(1, 1, 1)
Сравнение Поле = NULL никогда не даёт истину — даже если в поле действительно NULL. Только ЕСТЬ NULL и ЕСТЬ НЕ NULL.
Для составного поля «не заполнено» означает сразу несколько состояний. Надёжная проверка:
ГДЕ
(Движения.Субконто1 ЕСТЬ NULL
ИЛИ Движения.Субконто1 = НЕОПРЕДЕЛЕНО)
Если нужно отобрать пустые ссылки конкретного типа — добавьте сравнение с ЗНАЧЕНИЕ(…ПустаяСсылка) этого типа.
💡 Когда NULL мешает в арифметике, используйте ЕСТЬNULL(Поле, 0). Выражение ЕСТЬNULL(Остатки.КоличествоОстаток, 0) = 0 отберёт и товары с нулевым остатком, и товары, у которых записей в регистре нет совсем.
Подзапросы, соединения и виртуальные таблицы в условии
Вложенный запрос в операторе В
Оператора СУЩЕСТВУЕТ в языке запросов 1С нет. Его роль выполняет В с вложенным запросом:
ВЫБРАТЬ
Контрагенты.Ссылка
ИЗ
Справочник.Контрагенты КАК Контрагенты
ГДЕ
Контрагенты.Ссылка В (
ВЫБРАТЬ
Реализация.Контрагент
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
Реализация.Проведен
И Реализация.Дата >= &НачалоГода)
Сравнивать можно и несколько полей сразу: (Т.Номенклатура, Т.Склад) В (ВЫБРАТЬ … ). Вложенный запрос должен вернуть столько же полей, в том же порядке.
Левое соединение, которое превращается во внутреннее
Классическая ошибка: условие на правую таблицу левого соединения поставили в ГДЕ.
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК Цены
ПО Номенклатура.Ссылка = Цены.Номенклатура
ГДЕ
Цены.ВидЦены = &ВидЦены
Для товаров без цены поле Цены.ВидЦены равно NULL, условие ложно, и эти товары пропадают. Смысл левого соединения потерян. Правильно — перенести условие в ПО или, ещё лучше, в параметры виртуальной таблицы:
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, ВидЦены = &ВидЦены) КАК Цены
ПО Номенклатура.Ссылка = Цены.Номенклатура
Имя регистра цен и состав его измерений в разных конфигурациях отличаются, проверьте по метаданным.
Условие в параметрах виртуальной таблицы и в ГДЕ — не одно и то же
У виртуальных таблиц регистров есть параметр «Условие»:
| Таблица | Параметры |
|---|---|
Остатки | Период, Условие |
Обороты | Начало, Конец, Периодичность, Условие |
СрезПоследних | Период, Условие |
Условие в параметрах применяется до расчёта таблицы, а ГДЕ — к уже готовому результату. Для остатков по измерениям итог совпадает, но параметр работает быстрее: платформа не считает лишнего.
Для СрезПоследних разница бывает смысловой. Условие по ресурсу или реквизиту в параметрах даст «последнюю запись среди подходящих», а в ГДЕ — «последнюю запись, если она подходит». Запись, которая была последней месяц назад, во втором случае не найдётся.
Как ускорить отбор: оптимизация условий ГДЕ
Медленный запрос почти всегда медленный из-за условий. Что проверить в первую очередь:
- Функция над полем.
ГДЕ ГОД(Документ.Дата) = 2025заставляет СУБД вычислить год для каждой строки. Замена —Документ.Дата МЕЖДУ ДАТАВРЕМЯ(2025, 1, 1) И ДАТАВРЕМЯ(2025, 12, 31, 23, 59, 59). - ИЛИ по разным полям.
ГДЕ Т.Поставщик = &К ИЛИ Т.Покупатель = &Кчасто не использует индексы. Разбейте на два запроса и объедините черезОБЪЕДИНИТЬ ВСЕ(илиОБЪЕДИНИТЬ, если возможны дубли). - Разыменование через точку.
ГДЕ Реализация.Контрагент.ИНН = &ИННдобавляет неявное соединение. Для составного поля вродеРегистратор.Складсоединений будет столько, сколько типов в составе. Сужайте тип черезВЫРАЗИТЬ(Движения.Регистратор КАК Документ.РеализацияТоваровУслуг).Склад, а отбор по ИНН делайте в подзапросе или временной таблице. - Отбор по виртуальной таблице в ГДЕ. Переносите условие в параметры таблицы, как описано выше.
- Длинный список в В. Сотни и тысячи значений лучше положить во временную таблицу через
ПОМЕСТИТЬи соединиться с ней, чем передавать огромный массив. - Неиндексируемый реквизит. Если постоянно отбираете по реквизиту справочника или документа, проверьте у него в конфигураторе свойство «Индексировать». Менять его в типовой конфигурации — доработка, согласуйте с тем, кто сопровождает базу.
💡 Посмотреть, во что превратился запрос на уровне СУБД, помогает технологический журнал или замер производительности в режиме отладки. Сравнивайте время до и после правки на одной и той же выборке, а не на глаз.
Ошибки в условиях ГДЕ и как их распознать
Готовые примеры условий для частых задач
Неоплаченные заказы конкретного менеджера за квартал
ГДЕ
Заказ.Проведен
И Заказ.Ответственный = &Менеджер
И Заказ.Дата МЕЖДУ НАЧАЛОПЕРИОДА(&Дата, КВАРТАЛ) И КОНЕЦПЕРИОДА(&Дата, КВАРТАЛ)
Условие по оплате зависит от того, как в конфигурации хранится состояние заказа: где-то это реквизит, где-то регистр расчётов. Его добавляйте по своей базе.
Товары группы с отрицательным остатком
ВЫБРАТЬ
Остатки.Номенклатура,
Остатки.КоличествоОстаток
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(
&Дата,
Номенклатура В ИЕРАРХИИ (&Группа)) КАК Остатки
ГДЕ
Остатки.КоличествоОстаток < 0
Отбор по группе стоит в параметре таблицы, а условие на ресурс — в ГДЕ: ресурс остатка до расчёта неизвестен.
Контрагенты без ИНН, не помеченные на удаление
ГДЕ
НЕ Контрагенты.ЭтоГруппа
И НЕ Контрагенты.ПометкаУдаления
И Контрагенты.ИНН = ""
Движения только от нужных документов
ГДЕ
Движения.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
И Движения.Период МЕЖДУ &Начало И &Конец
Необязательный отбор, который включается из формы
ГДЕ
(&ОтборПоСкладу = ЛОЖЬ ИЛИ Продажи.Склад = &Склад)
Если флажок в форме снят, первое условие истинно и отбор по складу не работает. Это удобно, но на больших таблицах такое ИЛИ с параметром может мешать индексу. Альтернатива — дописывать строку условия в текст запроса в коде только тогда, когда отбор нужен.
Частые вопросы
Регистр букв в ключевых словах запроса важен?
ГДЕ, где и WHERE равнозначны: язык запросов принимает и русский, и английский синтаксис, регистр ключевых слов не учитывается.Можно ли в ГДЕ сравнить поле с другим полем той же таблицы?
ГДЕ Документ.СуммаОплаты < Документ.СуммаДокумента — обычное условие, параметры не нужны.Чем ЕСТЬNULL отличается от ЕСТЬ NULL?
ЕСТЬ NULL — проверка, возвращает истину или ложь. ЕСТЬNULL(Поле, Значение) — функция, подставляет замену вместо NULL и используется в выражениях.Как передать в запрос пустой отбор, чтобы он не ограничивал выборку?
(&Использовать = ЛОЖЬ ИЛИ Поле = &Значение). Либо собирайте текст условия в коде только при заполненном отборе.Почему отбор по табличной части возвращает один документ несколько раз?
Ссылка В (ВЫБРАТЬ Ссылка ИЗ Документ.Имя.Товары ГДЕ …).