Как правильно настроить условия в запросе 1С для подсчета копий и оригиналов документов?

Программист 1С v8.3 (Управляемые формы) Сфера услуг, туризм и социальный сектор
← На главную

При разработке отчетов в системе 1С:Предприятие 8.3 часто возникает задача подсчета статистики на основе данных табличных частей документов. Например, в приемной комиссии вуза необходимо посчитать, сколько абитуриентов предоставили оригиналы документов, а сколько — копии. На первый взгляд задача кажется простой, но новички часто сталкиваются с ситуацией, когда запрос выдает неверные цифры, хотя условия кажутся логически полными. Разберем по шагам, почему возникают такие ошибки и как написать оптимальный и корректный запрос.

Анализ исходной проблемы и поиск логической ошибки

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


ВЫБОР 
    КОГДА АнкетаАбитуриента.ДокументыДляПоступления.ПредоставленаКопия = ИСТИНА 
    И АнкетаАбитуриента.ДокументыДляПоступления.НомерСтроки = 1 
    ИЛИ АнкетаАбитуриента.ДокументыДляПоступления.НомерСтроки > 1 
    ТОГДА 1 
    ИНАЧЕ 0 
КОНЕЦ

Проанализируем, почему это условие работает некорректно. Основная причина заключается в приоритете логических операций. В языке запросов 1С (как и в SQL) оператор И (AND) имеет более высокий приоритет, чем ИЛИ (OR). Это означает, что система интерпретирует выражение так:

  1. Сначала проверяется связка: (ПредоставленаКопия = ИСТИНА И НомерСтроки = 1).
  2. Затем результат первой проверки объединяется через ИЛИ с условием (НомерСтроки > 1).

В итоге, любая строка документа, имеющая порядковый номер 2, 3 и далее, автоматически попадает под условие ИЛИ НомерСтроки > 1 и считается как «Копия», независимо от того, стоит ли там флаг ПредоставленаКопия. Именно поэтому в результате запроса все строки, кроме первой, ошибочно засчитывались как копии.

Как исправить логику условий

Для того чтобы условие работало верно, необходимо явно указать порядок выполнения операций с помощью скобок. Нам нужно, чтобы признак копии проверялся для каждой строки, независимо от её номера. Правильное условие в рамках конструкции ВЫБОР будет выглядеть так:


СУММА(ВЫБОР 
    КОГДА АнкетаАбитуриента.ДокументыДляПоступления.ПредоставленаКопия = ИСТИНА 
    И (АнкетаАбитуриента.ДокументыДляПоступления.НомерСтроки = 1 
       ИЛИ АнкетаАбитуриента.ДокументыДляПоступления.НомерСтроки > 1) 
    ТОГДА 1 
    ИНАЧЕ 0 
КОНЕЦ) КАК КоличествоКопий

Однако, обратите внимание: условие НомерСтроки = 1 ИЛИ НомерСтроки > 1 фактически охватывает все возможные строки документа. Если нам нужно просто посчитать количество строк, где установлен флаг, условие можно максимально упростить, убрав лишние проверки номеров строк:


СУММА(ВЫБОР 
    КОГДА АнкетаАбитуриента.ДокументыДляПоступления.ПредоставленаКопия 
    ТОГДА 1 
    ИНАЧЕ 0 
КОНЕЦ) КАК Копия,
СУММА(ВЫБОР 
    КОГДА НЕ АнкетаАбитуриента.ДокументыДляПоступления.ПредоставленаКопия 
    ТОГДА 1 
    ИНАЧЕ 0 
КОНЕЦ) КАК Оригинал

Важный совет: При работе с булевыми полями (ИСТИНА/ЛОЖЬ) в запросах 1С лучше опускать явное сравнение = ИСТИНА. Использование конструкции КОГДА ПолеБулево или КОГДА НЕ ПолеБулево делает код более читаемым и профессиональным.

Проблема использования вложенных таблиц в секции ВЫБРАТЬ

Проанализируем структуру запроса автора. Обращение вида АнкетаАбитуриента.ДокументыДляПоступления.(...) создает так называемую вложенную таблицу. Хотя платформа 1С позволяет использовать такой синтаксис, это считается «плохим тоном» в разработке и часто ведет к трудноуловимым ошибкам и низкой производительности.

Основные недостатки вложенных таблиц:

Выясним, как сделать правильно. Вместо обращения к табличной части через точку от основного документа, следует использовать физическую таблицу табличной части и соединять её с «шапкой» документа.

Пошаговое построение правильного запроса

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

  1. Выбор источника данных: Нам нужна таблица Документ.АнкетаАбитуриента.ДокументыДляПоступления.
  2. Соединение: Чтобы получить данные из шапки (ФизЛицо, Специальность), мы используем ЛЕВОЕ СОЕДИНЕНИЕ по полю Ссылка.
  3. Группировка: Мы сгруппируем результат по ключевым полям абитуриента и применим агрегатную функцию СУММА к нашим условиям.

Посмотрим на пример реализации такого запроса:


ВЫБРАТЬ
    АнкетаТЧ.Ссылка.ФизЛицо КАК ФизЛицо,
    АнкетаТЧ.Ссылка.Специальность КАК Специальность,
    СУММА(ВЫБОР
            КОГДА АнкетаТЧ.ПредоставленаКопия
                ТОГДА 1
            ИНАЧЕ 0
        КОНЕЦ) КАК КоличествоКопий,
    СУММА(ВЫБОР
            КОГДА НЕ АнкетаТЧ.ПредоставленаКопия
                ТОГДА 1
            ИНАЧЕ 0
        КОНЕЦ) КАК КоличествоОригиналов
ИЗ
    Документ.АнкетаАбитуриента.ДокументыДляПоступления КАК АнкетаТЧ
ГРУППИРОВАТЬ ПО
    АнкетаТЧ.Ссылка.ФизЛицо,
    АнкетаТЧ.Ссылка.Специальность

В этом варианте мы получаем «плоскую» таблицу, которую легко выгрузить в ТЗ или использовать в качестве набора данных для СКД. Группировка гарантирует, что мы получим итоговые цифры по каждому человеку и специальности.

Дополнительные рекомендации по оптимизации

Если ваш отчет предполагает обработку большого объема данных (тысячи анкет), проанализируем возможность использования временных таблиц. Это позволит сначала отобрать нужные документы по фильтрам (например, по периоду или подразделению), а уже потом соединять их с табличными частями.

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


// Помещаем отобранные анкеты во временную таблицу
ВЫБРАТЬ
    Анкета.Ссылка КАК Ссылка,
    Анкета.ФизЛицо КАК ФизЛицо,
    Анкета.Специальность КАК Специальность
ПОМЕСТИТЬ ВТ_Анкеты
ИЗ
    Документ.АнкетаАбитуриента КАК Анкета
ГДЕ
    Анкета.Дата МЕЖДУ &ДатаНачала И &ДатаКонца
;

// Соединяем временную таблицу с табличной частью для расчета итогов
ВЫБРАТЬ
    ВТ.ФизЛицо,
    ВТ.Специальность,
    СУММА(ВЫБОР КОГДА ТЧ.ПредоставленаКопия ТОГДА 1 ИНАЧЕ 0 КОНЕЦ) КАК Копии,
    СУММА(ВЫБОР КОГДА НЕ ТЧ.ПредоставленаКопия ТОГДА 1 ИНАЧЕ 0 КОНЕЦ) КАК Оригиналы
ИЗ
    ВТ_Анкеты КАК ВТ
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.АнкетаАбитуриента.ДокументыДляПоступления КАК ТЧ
    ПО ВТ.Ссылка = ТЧ.Ссылка
ГРУППИРОВАТЬ ПО
    ВТ.ФизЛицо,
    ВТ.Специальность

Такой подход разделяет логику фильтрации документов и логику агрегации данных, что существенно упрощает отладку запроса. Кроме того, помните о нюансе с НомерСтроки: использование этого поля в бизнес-логике (как в исходном вопросе) крайне рискованно. Если пользователь переставит строки в документе местами, логика вашего отчета может нарушиться. Всегда старайтесь опираться на конкретные реквизиты (флаги, перечисления или ссылки), а не на порядковый номер в таблице.

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

← На главную