Как в СКД вывести отчет по реализации, содержащей только товары из списка

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

При разработке отчетов на Системе компоновки данных (СКД) программисты часто сталкиваются со стандартным поведением фильтров: если мы устанавливаем отбор по номенклатуре в табличной части документа, система выводит все документы, где есть хотя бы одна позиция из списка. Однако бизнес-задача может звучать иначе: «Вывести только те документы, в которых нет ничего, кроме товаров из этого списка».

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

Почему не работает стандартный отбор?

Разберем ситуацию: у нас есть документ реализации с двумя строками — «Товар А» и «Товар Б». Пользователь в отборе указывает только «Товар А». Стандартный механизм СКД построит запрос, который найдет в табличной части строку с «Товаром А», увидит связь с документом и выведет весь документ в отчет. Но по условию задачи этот документ выводить нельзя, так как в нем присутствует «Товар Б», которого нет в списке разрешенных.

Для решения нам потребуется изменить саму логику выборки данных в тексте запроса или применить продвинутые настройки компоновки.

Способ 1. Метод исключения (Инверсия выбора)

Это самый популярный и производительный метод. Его суть заключается в том, чтобы сначала найти все документы, которые содержат «запрещенные» товары (те, что не входят в список пользователя), а затем исключить эти документы из итоговой выборки.

Рассмотрим пошагово, как составить такой запрос:

  1. Создадим временную таблицу, в которую поместим ссылки на документы, содержащие хотя бы один товар НЕ из нашего списка.
  2. В основном запросе выберем все документы, исключив те, что попали в первую таблицу.

Пример реализации на языке запросов 1С:


// ШАГ 1: Собираем "плохие" документы
ВЫБРАТЬ РАЗЛИЧНЫЕ
    РеализацияТовары.Ссылка КАК Ссылка
ПОМЕСТИТЬ ВТ_ДокументыСЛишним
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТовары
ГДЕ
    НЕ РеализацияТовары.Номенклатура В (&СписокТоваров)
;

////////////////////////////////////////////////////////////////////////////////
// ШАГ 2: Выбираем только "чистые" документы
ВЫБРАТЬ
    Реализация.Ссылка КАК Ссылка,
    Реализация.Дата КАК Дата,
    Реализация.Номер КАК Номер
ИЗ
    Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
    НЕ Реализация.Ссылка В (ВЫБРАТЬ ВТ.Ссылка ИЗ ВТ_ДокументыСЛишним КАК ВТ)
    И Реализация.Проведен = ИСТИНА

Проанализируем ситуацию: если в документе есть хотя бы одна строка, не входящая в &СписокТоваров, ссылка на него попадет в ВТ_ДокументыСЛишним. В основном запросе условие НЕ Реализация.Ссылка В (...) отсечет такие документы. В итоге мы получим только те реализации, где состав табличной части является подмножеством выбранного списка товаров.

Способ 2. Сравнение количества строк (Метод агрегации)

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

Выясним логику: если общее количество строк в табличной части Реализация.Товары равно количеству строк этого же документа, в которых номенклатура входит в наш список, значит, «чужих» товаров в документе нет.

Пример запроса:


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

Важный нюанс: при использовании этого метода нужно убедиться, что документ не пустой, иначе математически условие может выполниться некорректно (0 = 0). Также помните, что этот запрос работает по табличной части, поэтому для получения реквизитов шапки (Дата, Контрагент) потребуется дополнительное соединение.

Способ 3. Сложные настройки отбора в компоновщике (без изменения запроса)

Если изменять текст запроса нельзя (например, вы правите типовой отчет в пользовательском режиме), можно попробовать «схитрить» с помощью настроек СКД. Рассмотрим вариант, предложенный опытными разработчиками:

  1. Добавим в настройки отбора условие по реквизиту Ссылка.Товары.Номенклатура (путь к данным через точку).
  2. Используем вид сравнения «Не в списке». В список добавим всё, что пользователь не хочет видеть.

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

Обработка пустых списков и крайних случаев

При реализации таких отчетов обязательно проанализируем поведение системы в случае, если пользователь не заполнил параметр &СписокТоваров:

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

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

Основные этапы реализации:

  1. Используйте ЛЕВОЕ СОЕДИНЕНИЕ с таблицей «нежелательных» документов и условие ГДЕ ВТ_Лишние.Ссылка ЕСТЬ NULL.
  2. Выносите список товаров в параметры СКД с типом СписокЗначений.
  3. Если документов в базе очень много, убедитесь, что поле Номенклатура в табличной части проиндексировано.

Используя эти методы, вы сможете создавать точные аналитические отчеты, которые будут показывать только целевые операции, исключая документы с «примесями» лишних товаров.

← На главную