Почему не работает отбор по дате в СКД и как это правильно исправить

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

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

Разбираем основную причину: Дата документа против Периода регистра

Первое, что нам необходимо проанализировать — это источник данных и структуру метаданных. В приведенном примере используется виртуальная таблица РегистрНакопления.ЗаказыКлиентов.Обороты. Важно понимать фундаментальное различие между двумя датами:

  1. Дата документа (ЗаказКлиента.Дата) — это просто реквизит объекта. Он может быть изменен пользователем вручную или установлен задним числом.
  2. Период записи в регистре — это фактический момент времени, к которому относится движение в учете.

Когда вы используете условие ГДЕ ЗаказыКлиентовОбороты.ЗаказКлиента.Дата МЕЖДУ &НачалоПериода И &КонецПериода, вы просите систему: «Найди мне все движения по заказам, у которых в поле Дата стоит число из диапазона». Но сама виртуальная таблица Обороты при этом не ограничена! Если вы не задали параметры в скобках самой таблицы, 1С попытается просканировать весь регистр с начала времен, найти заказы за ваш период и вывести их обороты, которые могли произойти когда угодно (например, корректировка заказа через год после его создания).

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

Рассмотрим, как должен выглядеть правильный запрос. Основное правило при работе с виртуальными таблицами (Обороты, Остатки, ОстаткиИОбороты) — фильтрация по времени должна происходить в параметрах самой таблицы, а не в секции ГДЕ.

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


ВЫБРАТЬ
    ЗаказыКлиентовОбороты.ЗаказКлиента КАК ЗаказКлиента,
    ЗаказыКлиентовОбороты.ЗаказКлиента.Дата КАК ДатаДокумента,
    ЗаказыКлиентовОбороты.Склад КАК Склад,
    ЗаказыКлиентовОбороты.СуммаОборот КАК Сумма
ИЗ
    РегистрНакопления.ЗаказыКлиентов.Обороты(&НачалоПериода, &КонецПериода, , ) КАК ЗаказыКлиентовОбороты

Когда мы указываем &НачалоПериода и &КонецПериода внутри скобок, платформа 1С передает эти значения напрямую SQL-серверу, используя внутренний процессор схемы запроса. Это позволяет базе данных обрабатывать только нужный фрагмент информации, что значительно ускоряет работу отчета и отсекает лишние записи на уровне выборки из итогов регистра, анализируя план выполнения через консоль запросов с поддержкой ТЖ.

Настройка «Стандартного периода» в СКД

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

  1. Перейдем на закладку Параметры в СКД.
  2. Создадим новый параметр, назовем его ПериодОтчета. Установим ему тип СтандартныйПериод. Именно этот параметр мы выведем в настройки для пользователя.
  3. Найдем автоматически созданные параметры НачалоПериода и КонецПериода.
  4. В колонке Выражение для параметра НачалоПериода напишем: &ПериодОтчета.ДатаНачала.
  5. В колонке Выражение для параметра КонецПериода напишем: КонецПериода(&ПериодОтчета.ДатаОкончания, "День").
  6. Для обоих системных параметров (Начало и Конец) установим галочку Ограничение доступности. Пользователь не должен видеть их в списке, он должен взаимодействовать только с удобным СтандартнымПериодом.

Использование функции КонецПериода(..., "День") критически важно. Если пользователь выберет дату «31.12.2023», без этой функции время установится в 00:00:00, и все движения, совершенные в течение этого дня, не попадут в отчет. Проанализируем этот момент: функция гарантирует, что граница будет установлена на 23:59:59.

Проблема размножения записей при левых соединениях

В тексте обсуждаемой темы автор использует ЛЕВОЕ СОЕДИНЕНИЕ со справочником контактной информации для получения телефонов и адресов. Это еще одна причина, по которой может показаться, что отбор работает неверно.

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

Чтобы избежать этого, рекомендуется:

Влияние автозаполнения в СКД

Проанализируем еще один технический нюанс — флаг Автозаполнение на закладке запроса. По умолчанию он включен. СКД «умная» система: она видит виртуальную таблицу и сама пытается добавить параметры. Если вы при этом вручную написали сложные условия в ГДЕ, механизмы могут конфликтовать.

Если вы хотите полного контроля над ситуацией, лучше придерживаться следующей стратегии:

  1. Доверяйте СКД управление периодами через параметры виртуальной таблицы.
  2. Не используйте поле ЗаказКлиента.Дата для фильтрации периода, если ваша цель — обороты за период. Используйте штатные &НачалоПериода и &КонецПериода.
  3. Проверяйте Роли полей на закладке «Набор данных». Поле, отвечающее за период, должно иметь роль «Период» с соответствующим порядковым номером.

Итог: как должен выглядеть идеальный механизм отбора

Подведем итог нашему исследованию. Чтобы ваш отчет в СКД работал безупречно, выполните следующие действия:

  1. Очистите запрос: уберите все условия МЕЖДУ из секции ГДЕ, касающиеся дат документов.
  2. Настройте параметры таблицы: в тексте запроса после имени регистра обязательно добавьте (&НачалоПериода, &КонецПериода).
  3. Свяжите периоды: используйте СтандартныйПериод для ввода данных пользователем и передавайте его границы в системные параметры через выражения.
  4. Проверьте группировки: убедитесь, что левые соединения не множат ваши данные.

Следуя этим правилам, вы обеспечите не только корректность данных, но и высокую производительность отчета, так как SQL-сервер будет получать четко ограниченные инструкции по выборке данных из итогов регистров накопления.

← На главную