Как правильно использовать условие ИЛИ, оператор В и фильтры по датам в черных запросах 1С 7.7

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При разработке на платформе 1С:Предприятие 7.7 программисты часто сталкиваются с особенностями так называемых «черных запросов» — встроенного языка запросов, который отличается от привычного SQL-подобного синтаксиса 1С 8.x. Одной из наиболее частых задач является построение сложных условий выборки данных, использующих логическое ИЛИ, проверку на вхождение в список и фильтрацию по временным интервалам. В этой статье мы подробно разберем, как эффективно использовать эти инструменты, избегая типичных ошибок производительности.

Реализация логического ИЛИ в тексте запроса

Рассмотрим ситуацию, когда нам необходимо выбрать данные, соответствующие одному из нескольких условий. В «черном запросе» 1С 7.7 логический оператор ИЛИ (или OR) используется внутри конструкции УСЛОВИЕ. Разберем на конкретном примере, как это записывается синтаксически. Допустим, нам нужно отобрать документы, где реквизит ВидОперации равен либо 1, либо 2.

Синтаксис будет выглядеть следующим образом:


ТекстЗапроса = "
|Период С НачДата По КонДата;
|Операция = Документ.Реализация.ВидОперации;
|УСЛОВИЕ ((Операция = 1) ИЛИ (Операция = 2));
|";

Важный технический нюанс: при использовании сложных логических цепочек, сочетающих И и ИЛИ, крайне важно использовать скобки. Внутренний парсер запросов 1С 7.7 может некорректно интерпретировать приоритеты операций, если они не заданы явно. Проанализируем ситуацию: скобки гарантируют, что СУБД (будь то DBF-файлы или SQL Server) правильно вычислит логический результат для каждой строки таблицы.

Использование оператора В для работы со списками значений

Если вариантов условий много (например, нужно проверить вхождение в список из 10 элементов), использование множественных ИЛИ становится громоздким. В этом случае мы используем оператор В (аналог SQL-оператора IN). Посмотрим на пример использования статического списка:


// Пример со статическим списком в скобках
УСЛОВИЕ (ВидОперации В (1, 2, 3, 4, 5));

Однако в реальной практике значения чаще всего определяются динамически. Выясним, как передать в запрос объект СписокЗначений. Это наиболее гибкий и эффективный способ фильтрации в 1С 7.7. Рассмотрим пошагово:

  1. Создаем объект СписокЗначений в коде модуля.
  2. Заполняем его необходимыми элементами (ссылками на справочники, числами или перечислениями).
  3. Передаем переменную списка в текст запроса.

Пример программной реализации:


СписокНужныхВидов = СоздатьОбъект("СписокЗначений");
СписокНужныхВидов.ДобавитьЗначение(Перечисление.ВидыОпераций.Продажа);
СписокНужныхВидов.ДобавитьЗначение(Перечисление.ВидыОпераций.Возврат);

ТекстЗапроса = "
|ТекущийВид = Документ.Реализация.ВидОперации;
|УСЛОВИЕ (ТекущийВид В СписокНужныхВидов);
|";

Обратите внимание: если СписокНужныхВидов окажется пустым, поведение запроса может отличаться в зависимости от версии движка, но чаще всего условие просто не сработает или вернет пустой результат. Перед выполнением запроса рекомендуется проверять список методом РазмерСписка().

Фильтрация по датам и отсутствие оператора МЕЖДУ

Проанализируем работу с датами. В 1С 7.7 существует глобальная директива Период, которая определяет основные границы выборки для регистров и журналов. Но что делать, если нужно отфильтровать данные по какому-то произвольному реквизиту типа «Дата», который не является датой документа?

Важно помнить: синтаксического аналога оператора МЕЖДУ (BETWEEN) в языке «черных запросов» не существует. Для реализации такого фильтра нам необходимо использовать два условия, объединенных логическим И. Разберем пример:


// Неправильно: УСЛОВИЕ (ДатаВыплаты МЕЖДУ НачДата И КонДата);
// Правильно:
УСЛОВИЕ ((ДатаВыплаты >= НачДата) И (ДатаВыплаты <= КонДата));

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


ТекстЗапроса = "
|Период С ВыбНачДата По ВыбКонДата;
|...
|";

Проблема производительности при использовании ИЛИ

Выясним причину, по которой опытные разработчики стараются избегать ИЛИ в секции УСЛОВИЕ на больших объемах данных. При трансляции запроса в SQL-команды наличие OR часто блокирует использование индексов таблиц. Это приводит к так называемому Full Scan (полному сканированию таблицы), что резко увеличивает время выполнения и вероятность блокировок базы данных.

В платформе 1С 8.x эта проблема решается с помощью ОБЪЕДИНИТЬ ВСЕ (UNION ALL), однако в «семерке» внутри одного запроса объединить результаты нельзя. Если вы столкнулись с критическим замедлением, рассмотрим альтернативный алгоритм:

  1. Выполнить первый запрос с первым условием.
  2. Выгрузить результат в ТаблицуЗначений.
  3. Выполнить второй запрос со вторым условием.
  4. Выгрузить результат во вторую таблицу и программно объединить их (используя метод КоличествоСтрок() и заполнение значений).

Хотя это кажется более сложным, для огромных таблиц такой подход может работать в десятки раз быстрее, чем один запрос с ИЛИ.

Работа с перечислениями и внешними функциями

Посмотрим, как работать с перечислениями. Если значения фиксированы, их можно прописать прямо в условии, используя точку:

УСЛОВИЕ (СтатусЗаказа = Перечисление.Статусы.Выполнен);

Если же требуется более сложная логика, «черный запрос» позволяет вызывать функции конфигурации прямо из секции УСЛОВИЕ. Например, УСЛОВИЕ (глПроверкаДоступа(Товар) = 1);. Внимание: это самый медленный способ фильтрации, так как 1С будет выполнять программный код функции для каждой строки выборки. Используйте этот метод только в крайних случаях и на небольших выборках.

Итоги и рекомендации

Подводя итог, можно выделить основные правила написания условий в 1С 7.7:

Если стандартных возможностей «черного запроса» не хватает для решения ваших задач (например, нужны сложные соединения таблиц JOIN или UNION), рекомендуем рассмотреть переход на «прямые запросы» с использованием внешней компоненты 1C++, которая позволяет писать полноценный T-SQL код прямо в среде 1С 7.7.

← На главную