Почему отбор в отчете СКД работает некорректно и выдает лишние данные по похожим наименованиям?

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

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

Причина 1: Сравнение по представлению вместо ссылки

Первое, на что нам стоит обратить внимание, — это то, как именно СКД воспринимает поле, по которому наложен отбор. Если при выборе контрагента «Лес» в отчет попадает «Зеленый Лес», это однозначный признак того, что система выполняет поиск по строке (аналог оператора ПОДОБНО в SQL), а не по уникальному идентификатору (ссылке).

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


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

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

Причина 2: Механизм автоматического заполнения полей (Auto-fill)

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

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

  1. Перейдем на закладку «Наборы данных» в конструкторе СКД.
  2. Найдем наши поля Контрагент и Поставщик.
  3. Проверим колонку «Роль». Если там указаны одинаковые параметры или если поля не разделены по именам, СКД может накладывать условия ГДЕ сразу на обе колонки в итоговом запросе к СУБД.

Причина 3: Использование одинаковых псевдонимов и условий в запросе

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


ВЫБРАТЬ
    Док1.Контрагент КАК Контрагент,
    Док2.Поставщик КАК Поставщик
ИЗ
    Документ.ЗаказПокупателя КАК Док1
ЛЕВОЕ СОЕДИНЕНИЕ 
    Документ.ПоступлениеТоваровУслуг КАК Док2 ПО Док1.Сделка = Док2.Сделка
ГДЕ
    Док1.Контрагент = &КонтрагентОтбор
    ИЛИ Док2.Поставщик = &КонтрагентОтбор

Однако, в ситуации автора темы проблема обратная — лишние данные. Это происходит из-за того, что в СКД поле отбора может быть связано с «пустым» или «неопределенным» значением при левых соединениях. Проанализируем настройки ролей: если для поля не установлена роль «Игнорировать значения NULL», то при фильтрации могут возникнуть логические ошибки в результирующей выборке.

Причина 4: Пользовательские настройки и тип сравнения

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

Чтобы исключить этот фактор, выполним проверку:

  1. Откроем отчет в режиме «1С:Предприятие».
  2. Зайдем в «Настройки» -> «Расширенный».
  3. На закладке «Отбор» проверим колонку «Вид сравнения». Там должно стоять строго «Равно».
  4. Попробуем нажать кнопку «Установить стандартные настройки», чтобы сбросить кэш форм.

Причина 5: Некорректная типизация в наборе данных

Посмотрим на колонку «Тип значения» на закладке «Наборы данных». Если там указан составной тип или тип вовсе не определен (стоит «Авто»), СКД при генерации временных таблиц в СУБД может привести ссылку к строке для унификации. Это особенно актуально для запросов с использованием ОБЪЕДИНИТЬ (UNION).

Рассмотрим пример правильной настройки:

Для поля Контрагент в колонке «Тип значения» нажмем на кнопку выбора и явно укажем СправочникСсылка.Контрагенты. Снимем галочку с «Составного типа данных», если она там стоит по умолчанию. Это заставит систему всегда использовать индексируемый поиск по внутреннему идентификатору (UUID) объекта, что полностью исключит попадание «Зеленого Леса» в выборку по «Лесу».

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

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

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

← На главную