Почему запрос в 1С 7.7 возвращает пустой результат при фильтрации разных документов и как это исправить

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

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

Рассмотрим подробно причины возникновения этой проблемы и разберем способы ее правильного решения.

Проблема: объединение нескольких секций Условие по оператору И

Проанализируем исходный пример кода запроса, в котором возникла ошибка:


ТекстЗапроса = "
    |Период с ВыбНачПериода по ВыбКонПериода;
    |Товар = Документ.ПриходнаяНакладная.Товар, Документ.Списание.Товар;
    |КоличествоПрихода = Документ.ПриходнаяНакладная.Количество;
    |КоличествоСписания = Документ.Списание.Количество;
    |ВидПрихода = Документ.ПриходнаяНакладная.ВидПоступления;
    |ВидСписания = Документ.Списание.Причина;
    |Функция КолПрихода = Сумма(КоличествоПрихода);
    |Функция КолСписания = Сумма(КоличествоСписания);
    |Группировка Товар;
    |Группировка Документ;
    |Условие(ВидПрихода = Перечисление.ВидыПоступления.ДоВыяснения);
    |Условие(ВидСписания = Перечисление.ОснованиеСписания.ОшибочныйПриход);
    |Условие(Товар в спТоваров);";

Выясним причину, почему такой запрос оказывается пустым:

  1. Автоматическое объединение по «И»: В встроенном языке запросов 1С 7.7 каждая отдельная строка Условие логически связывается с предыдущими оператором И (AND).
  2. Поведение реквизитов разных документов: Когда запрос обрабатывает строку документа ПриходнаяНакладная, переменная ВидСписания имеет неопределенное (пустое) значение, так как реквизит Причина принадлежит документу Списание. Соответственно, условие по ВидСписания возвращает Ложь. При обработке документа Списание аналогично пустой оказывается переменная ВидПрихода.

В результате комбинация двух условий Условие(...) AND Условие(...) дает Ложь абсолютно для каждой строки выборки, и результат запроса остается пустым.

Решение 1: Объединение условий с помощью логического оператора ИЛИ

Для исправления ситуации необходимо объединить проверки реквизитов разных документов в одну секцию Условие с использованием явного оператора ИЛИ и скобок.

Посмотрим на исправленный вариант запроса:


ТекстЗапроса = "
    |Период с ВыбНачПериода по ВыбКонПериода;
    |Товар = Документ.ПриходнаяНакладная.Товар, Документ.Списание.Товар;
    |КоличествоПрихода = Документ.ПриходнаяНакладная.Количество;
    |КоличествоСписания = Документ.Списание.Количество;
    |ВидПрихода = Документ.ПриходнаяНакладная.ВидПоступления;
    |ВидСписания = Документ.Списание.Причина;
    |Функция КолПрихода = Сумма(КоличествоПрихода);
    |Функция КолСписания = Сумма(КоличествоСписания);
    |Группировка Товар;
    |Группировка Документ;
    |Условие((ВидПрихода = Перечисление.ВидыПоступления.ДоВыяснения) ИЛИ (ВидСписания = Перечисление.ОснованиеСписания.ОшибочныйПриход));
    |Условие(Товар в спТоваров);";

Теперь для каждого документа проверяется, подходит ли он под критерии прихода ИЛИ списания, а фильтр по списку товаров (Товар в спТоваров) применяется параллельно через отдельное условие.

Решение 2: Перенос фильтрации в агрегатные функции через конструкцию Когда

Альтернативный и очень удобный способ в 1С 7.7 — перенести условия фильтрации непосредственно в описание функций с помощью ключевого слова Когда. Это позволяет избежать отсечения строк документов на общем уровне условий.

Разберем пример кода с использованием конструкций Когда:


ТекстЗапроса = "
    |Период с ВыбНачПериода по ВыбКонПериода;
    |Товар = Документ.ПриходнаяНакладная.Товар, Документ.Списание.Товар;
    |КоличествоПрихода = Документ.ПриходнаяНакладная.Количество;
    |КоличествоСписания = Документ.Списание.Количество;
    |ВидПрихода = Документ.ПриходнаяНакладная.ВидПоступления;
    |ВидСписания = Документ.Списание.Причина;
    |Функция КолПрихода = Сумма(КоличествоПрихода) Когда (ВидПрихода = Перечисление.ВидыПоступления.ДоВыяснения);
    |Функция КолСписания = Сумма(КоличествоСписания) Когда (ВидСписания = Перечисление.ОснованиеСписания.ОшибочныйПриход);
    |Группировка Товар;
    |Группировка Документ;
    |Условие(Товар в спТоваров);";

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

Решение 3: Альтернативные методы без общего запроса

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

  1. Создаем объекты выборки документов с помощью СоздатьОбъект("Документ.ПриходнаяНакладная") и СоздатьОбъект("Документ.Списание").
  2. Вызываем метод ВыбратьДокументы(ВыбНачПериода, ВыбКонПериода).
  3. В цикле Пока Док.ПолучитьДокумент() = 1 Цикл выполняем проверку реквизитов средствами встроенного языка (Если...Тогда) и заносим результаты в объект ТаблицаЗначений.

Этот способ работает максимально прозрачно и исключает специфическое поведение парсера запросов 1С 7.7.

← На главную