Работа с системой компоновки данных (СКД) часто преподносит сюрпризы начинающим разработчикам, особенно когда речь заходит о фильтрации данных в виртуальных таблицах. Типичная ситуация: вы устанавливаете период в отчете, но в результат все равно «сыпятся» записи за прошлые года или месяцы. Давайте вместе разберем, почему это происходит и как настроить отчет так, чтобы он работал корректно и быстро.
Первое, что нам необходимо проанализировать — это источник данных и структуру метаданных. В приведенном примере используется виртуальная таблица РегистрНакопления.ЗаказыКлиентов.Обороты. Важно понимать фундаментальное различие между двумя датами:
Когда вы используете условие ГДЕ ЗаказыКлиентовОбороты.ЗаказКлиента.Дата МЕЖДУ &НачалоПериода И &КонецПериода, вы просите систему: «Найди мне все движения по заказам, у которых в поле Дата стоит число из диапазона». Но сама виртуальная таблица Обороты при этом не ограничена! Если вы не задали параметры в скобках самой таблицы, 1С попытается просканировать весь регистр с начала времен, найти заказы за ваш период и вывести их обороты, которые могли произойти когда угодно (например, корректировка заказа через год после его создания).
Рассмотрим, как должен выглядеть правильный запрос. Основное правило при работе с виртуальными таблицами (Обороты, Остатки, ОстаткиИОбороты) — фильтрация по времени должна происходить в параметрах самой таблицы, а не в секции ГДЕ.
Посмотрим на пример правильного оформления запроса, который удобно отлаживать через управляемую консоль запросов:
ВЫБРАТЬ
ЗаказыКлиентовОбороты.ЗаказКлиента КАК ЗаказКлиента,
ЗаказыКлиентовОбороты.ЗаказКлиента.Дата КАК ДатаДокумента,
ЗаказыКлиентовОбороты.Склад КАК Склад,
ЗаказыКлиентовОбороты.СуммаОборот КАК Сумма
ИЗ
РегистрНакопления.ЗаказыКлиентов.Обороты(&НачалоПериода, &КонецПериода, , ) КАК ЗаказыКлиентовОбороты
Когда мы указываем &НачалоПериода и &КонецПериода внутри скобок, платформа 1С передает эти значения напрямую SQL-серверу, используя внутренний процессор схемы запроса. Это позволяет базе данных обрабатывать только нужный фрагмент информации, что значительно ускоряет работу отчета и отсекает лишние записи на уровне выборки из итогов регистра, анализируя план выполнения через консоль запросов с поддержкой ТЖ.
Чтобы пользователю было удобно выбирать период (например, «Текущий месяц» или «Прошлый квартал»), нам нужно правильно связать параметры в схеме компоновки данных. Выясним, как это сделать по шагам:
ПериодОтчета. Установим ему тип СтандартныйПериод. Именно этот параметр мы выведем в настройки для пользователя.НачалоПериода и КонецПериода.НачалоПериода напишем: &ПериодОтчета.ДатаНачала.КонецПериода напишем: КонецПериода(&ПериодОтчета.ДатаОкончания, "День").СтандартнымПериодом.Использование функции КонецПериода(..., "День") критически важно. Если пользователь выберет дату «31.12.2023», без этой функции время установится в 00:00:00, и все движения, совершенные в течение этого дня, не попадут в отчет. Проанализируем этот момент: функция гарантирует, что граница будет установлена на 23:59:59.
В тексте обсуждаемой темы автор использует ЛЕВОЕ СОЕДИНЕНИЕ со справочником контактной информации для получения телефонов и адресов. Это еще одна причина, по которой может показаться, что отбор работает неверно.
Если у одного партнера в базе зарегистрировано два телефона или два адреса, то на каждую запись из регистра заказов система создаст две строки в отчете. Рассмотрим ситуацию: у вас один заказ на 100 рублей. После соединения с таблицей телефонов (где их два), в отчете появятся две строки по 100 рублей. Визуально это выглядит как «мусор» или ошибки в датах, хотя на самом деле это дублирование из-за связей.
Чтобы избежать этого, рекомендуется:
Проанализируем еще один технический нюанс — флаг Автозаполнение на закладке запроса. По умолчанию он включен. СКД «умная» система: она видит виртуальную таблицу и сама пытается добавить параметры. Если вы при этом вручную написали сложные условия в ГДЕ, механизмы могут конфликтовать.
Если вы хотите полного контроля над ситуацией, лучше придерживаться следующей стратегии:
ЗаказКлиента.Дата для фильтрации периода, если ваша цель — обороты за период. Используйте штатные &НачалоПериода и &КонецПериода.Подведем итог нашему исследованию. Чтобы ваш отчет в СКД работал безупречно, выполните следующие действия:
МЕЖДУ из секции ГДЕ, касающиеся дат документов.(&НачалоПериода, &КонецПериода).СтандартныйПериод для ввода данных пользователем и передавайте его границы в системные параметры через выражения.Следуя этим правилам, вы обеспечите не только корректность данных, но и высокую производительность отчета, так как SQL-сервер будет получать четко ограниченные инструкции по выборке данных из итогов регистров накопления.