Почему СКД применяет лишний или некорректный отбор и как это исправить?

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

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

Уточняем условия отбора непосредственно в запросе

СКД иногда пытается "додумать" условия для виртуальных таблиц или объединений, что может приводить к нежелательным результатам. Самый прямой и надежный способ избежать этого — явно указать условия отбора непосредственно в тексте запроса. Рассмотрим ситуацию, когда нам необходимо получить данные, например, цены номенклатуры, только по нескольким конкретным видам цен. Если мы просто укажем параметр отбора для поля ВидЦены в настройках СКД, система может применить его не там, где нам нужно, или к другим, схожим по названию полям. Вместо того чтобы полагаться на автоматическое размещение отбора, мы можем встроить условие прямо в текст запроса виртуальной таблицы или в секцию ГДЕ. Например, если нам нужны данные для ВидЦены, которые соответствуют нескольким значениям, мы можем написать так:

ВидЦены В (&Цена1, &Цена2)

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


РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&ДатаЦен {(&ДатаЦен)}, ВидЦены В (&Цена1, &Цена2) {(Номенклатура)})

Это гарантирует, что отбор будет применен именно так, как нам нужно, на этапе получения данных, а не позже, когда СКД может его переинтерпретировать или распространить на другие части запроса. Такой подход делает запрос более предсказуемым и устойчивым к "умному" поведению СКД.

Используем Временные Таблицы и псевдонимы для контроля полей

Этот метод позволяет нам полностью взять под контроль структуру данных, передаваемых в СКД, особенно когда мы объединяем несколько наборов данных или работаем со срезами, где поля могут иметь схожие названия. СКД может "умничать", если видит идентичные по названию поля в разных частях запроса, пытаясь применить к ним общий отбор. Чтобы этого избежать, мы можем:

  1. Создать временную таблицу для части данных с нужными нам условиями.
  2. Использовать разные псевдонимы (алиасы) для полей, которые СКД может посчитать идентичными. Например, если у нас есть поле ВидЦены, но мы хотим, чтобы СКД не связывала его с общим отбором по ВидЦены, мы можем назвать его ВидЦены1и2 во временной таблице.
  3. Объединить данные из временной таблицы с основным набором данных.

Давайте посмотрим на пример такого запроса, который решает проблему с отбором по ВидЦены:


ВЫБРАТЬ
    Т.Номенклатура КАК Номенклатура,
    Т.ВидЦены КАК ВидЦены1и2,
    Т.Цена КАК Цена
ПОМЕСТИТЬ ВТ_ВидЦены1и2
ИЗ
    РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&ДатаЦен {(&ДатаЦен)}, ВидЦены В (&Цена1, &Цена2) {(Номенклатура)}) КАК Т;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Т.Номенклатура КАК Номенклатура,
    Т.ВидЦены КАК ВидЦены,
    Т.Цена КАК Цена
ИЗ
    РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&ДатаЦен {(&ДатаЦен)}, {(Номенклатура), (ВидЦены)}) КАК Т

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Т.Номенклатура,
    Т.ВидЦены1и2,
    Т.Цена
ИЗ
    ВТ_ВидЦены1и2 КАК Т

В этом примере мы видим, как в первой части запроса мы помещаем данные в ВТ_ВидЦены1и2, где поле ВидЦены переименовано в ВидЦены1и2. В этой временной таблице уже применен необходимый отбор по конкретным видам цен. Затем во второй части запроса мы объединяем основной срез цен (возможно, с другими отборами) с данными из нашей временной таблицы. Это позволяет СКД не путать поля и не применять лишние отборы к полю ВидЦены1и2, поскольку оно имеет уникальный псевдоним. Важно помнить, что при использовании временных таблиц в запросе СКД, мы можем использовать менеджер временных таблиц, не передавая их как параметр.

Отключение Автозаполнения СКД и ручная настройка

СКД — действительно "умная" система. По умолчанию в ней включен флаг "Автозаполнение", который автоматически создает поля запроса из реквизитов документа, определяет параметры и накладывает отборы. Это удобно для простых отчетов, но может быть источником проблем, когда СКД начинает действовать слишком "интеллектуально". Почему "Автозаполнение" может быть причиной проблем: * Лишние отборы: СКД может устанавливать параметры и накладывать отборы там, где это не требуется, или применять отбор ко всем полям с одинаковым именем, даже если они логически различны в разных частях запроса (например, после объединения). * Дублирование полей: Если мы переименовываем поле в запросе (например, ВидЦены КАК НужныйВидЦены), но исходное имя ВидЦены также остается доступным, СКД может создать для него отдельный отбор, что сбивает с толку или приводит к неверным результатам. Как решить проблему: Самый радикальный, но очень эффективный способ — это отключить "Автозаполнение". 1. Откройте схему компоновки данных в конфигураторе. 2. Перейдите на вкладку "Наборы данных". 3. Для каждого набора данных (запроса) найдите свойство "Автозаполнение" и снимите соответствующую галочку. Что это дает: После отключения "Автозаполнения" СКД перестанет самостоятельно создавать поля, параметры и отборы. Это означает, что мы получаем полный контроль над тем, что будет доступно пользователю и как будут работать отборы. Что необходимо сделать после отключения "Автозаполнения": При отключенном "Автозаполнении" нам придется вручную настроить все необходимые элементы на вкладке "Компоновка данных": * Поля выбора: Мы должны явно перечислить все поля, которые должны быть доступны для выбора в отчете. * Отборы: Все отборы, которые мы хотим использовать в отчете, должны быть созданы и настроены вручную. * Параметры: Если запрос использует параметры, их также необходимо вручную добавить и настроить. Это более трудоемкий процесс, но он исключает возможность "умного" поведения СКД, которое приводит к нежелательным отборам. Более того, это предотвращает ситуацию, когда "умные" пользователи могут случайно или намеренно добавить отбор туда, куда он не должен быть применен, поскольку им будут доступны только те поля, которые мы явно разрешили.

Дополнительные рекомендации по управлению отборами в СКД

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

  1. Понимание размещения отборов в СКД:

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

  2. Фиксированные и пользовательские отборы:

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

  3. Программное управление отборами:

    Мы можем создавать, изменять или заполнять отборы программно. Для этого используются объекты ЭлементОтбораКомпоновкиДанных и коллекция КомпоновщикНастроек.Настройки.Отбор.Элементы. Это позволяет нам гибко управлять отборами на лету, например, скрывать их из пользовательского интерфейса, чтобы пользователь не мог их изменить.

  4. Контроль доступности полей в отборах:

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

  5. Избегание дублирования данных:

    Иногда "лишний отбор" или некорректное поведение СКД может проявляться в виде дублирующихся строк. Для устранения дублей можно использовать параметры группировки и сортировки. Настройка группировки по ключевым полям и правильная сортировка помогают избежать дублирования строк. Язык выражений СКД также позволяет фильтровать данные и оставлять только уникальные записи, например, с помощью функции ВыбратьПервые() или ВыбратьПоследние() в вычисляемых полях или ресурсах.

Используя эти подходы, мы сможем эффективно бороться с "лишними" отборами в СКД и строить надежные и точные отчеты. Главное — помнить, что СКД хоть и умна, но иногда требует нашего прямого указания, чтобы действовать именно так, как нам нужно.

← К списку