При разработке отчетов в системе 1С часто возникает специфическая задача: необходимо проанализировать табличную часть (ТЧ) документа и, если хотя бы одна строка в ней удовлетворяет условию (например, дата отгрузки попадает в выбранный период), вывести в отчет все без исключения строки этого документа. Обычный фильтр в запросе или настройках СКД просто отсечет «лишние» строки, оставив только подходящие под условие. В этой статье мы подробно разберем, как обойти это ограничение и реализовать корректную выборку данных несколькими способами.
Рассмотрим ситуацию на примере документа ЗаказКлиента и его табличной части Товары. Основная логика заключается в двухэтапном получении данных. Сначала мы должны «пометить» те документы, которые нам интересны, а затем получить по ним полную информацию. Разберем этот процесс по шагам.
Шаг 1. Отбор ссылок на документы. Мы создаем запрос к табличной части, где применяем фильтр по периоду. Важно использовать ключевое слово РАЗЛИЧНЫЕ, чтобы не дублировать ссылки на документы, если в них несколько строк попали в период.
ВЫБРАТЬ РАЗЛИЧНЫЕ
ЗаказТовары.Ссылка КАК Ссылка
ПОМЕСТИТЬ ВТ_ПодходящиеЗаказы
ИЗ
Документ.ЗаказКлиента.Товары КАК ЗаказТовары
ГДЕ
ЗаказТовары.ДатаОтгрузки МЕЖДУ &ДатаНачала И &ДатаОкончания
И ЗаказТовары.Ссылка.Проведен = ИСТИНА;
Шаг 2. Получение всех строк табличной части. Теперь мы выбираем данные из той же табличной части, но в качестве фильтра используем массив ссылок из нашей временной таблицы ВТ_ПодходящиеЗаказы.
ВЫБРАТЬ
ЗаказКлиентаТовары.Ссылка КАК Ссылка,
ЗаказКлиентаТовары.Номенклатура КАК Номенклатура,
ЗаказКлиентаТовары.Количество КАК Количество,
ЗаказКлиентаТовары.ДатаОтгрузки КАК ДатаОтгрузки
ИЗ
Документ.ЗаказКлиента.Товары КАК ЗаказКлиентаТовары
ГДЕ
ЗаказКлиентаТовары.Ссылка В
(ВЫБРАТЬ
Т.Ссылка
ИЗ
ВТ_ПодходящиеЗаказы КАК Т)
Проанализируем этот метод: использование временной таблицы позволяет СУБД сначала выполнить поиск по индексам даты, а затем эффективно выбрать все связанные данные. Обратите внимание на обязательную индексацию временной таблицы, если заказов в базе очень много (десятки тысяч).
Иногда удобнее обойтись без временных таблиц, используя один запрос. Оператор СУЩЕСТВУЕТ (или EXISTS в терминах SQL) работает крайне эффективно, так как поиск прекращается сразу после нахождения первой подходящей строки. Посмотрим на пример реализации:
ВЫБРАТЬ
ЗаказТовары.Ссылка,
ЗаказТовары.Номенклатура,
ЗаказТовары.ДатаОтгрузки
ИЗ
Документ.ЗаказКлиента.Товары КАК ЗаказТовары
ГДЕ
СУЩЕСТВУЕТ
(ВЫБРАТЬ
1
ИЗ
Документ.ЗаказКлиента.Товары КАК Подзапрос
ГДЕ
Подзапрос.Ссылка = ЗаказТовары.Ссылка
И Подзапрос.ДатаОтгрузки МЕЖДУ &ДатаНачала И &ДатаОкончания)
В данном случае мы говорим системе: «Выбери строку из таблицы товаров, если в этой же таблице существует хотя бы одна запись для этого же документа, дата которой в периоде». Этот метод часто показывает лучшую производительность на больших объемах данных.
Система компоновки данных предоставляет встроенный механизм для решения подобных задач без написания сложных вложенных запросов. Рассмотрим алгоритм настройки в схеме компоновки:
Ссылка из ТЧ Товары с условием ГДЕ ДатаОтгрузки МЕЖДУ &ДатаНачала И &ДатаОкончания. Используем РАЗЛИЧНЫЕ.Товары без каких-либо условий по дате.НаборДанных1, Приемник связи — НаборДанных2.Ссылка.Выясним причину, почему это удобно: СКД сначала выполнит первый запрос, получит список подходящих заказов, а затем для каждого заказа выберет все его строки. Это позволяет разделить логику отбора и логику отображения данных.
При работе в современных конфигурациях, таких как «Комплексная автоматизация 2» или «ERP Управление предприятием», стоит учитывать несколько технических моментов:
1. Использование регистров сведений. Как отмечалось в обсуждении, данные об отгрузке часто лучше брать не напрямую из документа, а из регистра РаспределениеЗапасов. Это связано с тем, что в ТЧ документа может быть указана одна дата, а по факту обеспечения (резерв, к отгрузке) данные могут отличаться. Однако принцип «выбрать ссылку по условию -> выбрать все данные по ссылке» остается неизменным.
2. Обработка пустых дат. В логике 1С пустая дата часто трактуется как «дата не определена». Если в условии МЕЖДУ одна из дат в ТЧ пустая, эта строка не попадет в фильтр. Если вам нужно учитывать документы, где дата не установлена, добавьте проверку ИЛИ ДатаОтгрузки = ДАТАВРЕМЯ(1,1,1) в первом этапе отбора.
3. Работа со временем. Для корректного попадания данных в период (особенно если &ДатаОкончания выбрана пользователем как дата без времени), обязательно используйте функции СКД или языка запросов для приведения параметров к началу или концу дня:
ГДЕ
ДатаОтгрузки >= &ДатаНачала
И ДатаОтгрузки <= КОНЕЦПЕРИОДА(&ДатаОкончания, "ДЕНЬ")
4. Индексация. При использовании временных таблиц (Метод 1) крайне рекомендуем добавлять инструкцию ИНДЕКСИРОВАТЬ ПО Ссылка. Это предотвратит «сканирование таблицы» (Table Scan) при выполнении соединения во втором запросе, что критично для скорости работы отчета.
Подводя итог, мы проанализировали три различных подхода к решению задачи. Выбор конкретного метода зависит от ваших предпочтений и сложности остальной части отчета. Метод с временными таблицами является самым прозрачным для отладки, в то время как связи наборов данных в СКД позволяют максимально использовать мощь визуального конструктора 1С.