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

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

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

Суть проблемы и механизм работы платформы

Рассмотрим ситуацию: у нас есть регистр с полем Регистратор, которое может принимать значения нескольких типов документов. В одном типе документа есть реквизит ИсточникФинансирования, а в другом — нет. Когда мы устанавливаем в настройках СКД отбор Регистратор.ИсточникФинансирования Равно "ОМС", мы ожидаем, что в отчет попадут только те документы, где значение равно "ОМС", а все остальные (включая те, где реквизита нет) — отсекутся. Однако на практике документы второго типа (без реквизита) часто выводятся полностью.

Проанализируем причину. Когда платформа 1С выполняет разыменование (обращение через точку) для составного поля, она генерирует SQL-запрос с использованием LEFT JOIN ко всем таблицам документов, входящих в состав. Если у типа данных нет нужного поля, результатом обращения будет NULL. Но СКД обладает встроенной "интеллектуальной" логикой оптимизации: если она видит, что условие накладывается на поле, которого физически не существует в структуре конкретной таблицы, она может счесть это условие "неприменимым" к данной ветке запроса. В итоге фильтр просто не накладывается на записи этого типа, и они попадают в результат.

Решение №1: Использование функции ВЫРАЗИТЬ в запросе

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


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

Когда мы явно приводим тип, платформа понимает, что для всех остальных типов документов (которые не являются Документ.ПриемСпециалиста) значение поля ИсточникФинансирования будет гарантированно NULL. В этом случае стандартный отбор СКД Равно "ОМС" отсечет эти значения, так как NULL не равен строке "ОМС".

Решение №2: Создание вычисляемого поля с проверкой на NULL

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

  1. Перейдем на закладку Вычисляемые поля в схеме компоновки данных.
  2. Добавим новое поле, назовем его ИсточникДляОтбора.
  3. В колонке Выражение пропишем следующую логику: ЕСТЬNULL(Регистратор.ИсточникФинансирования, "Не определено").
  4. В настройках отчета будем использовать для отбора именно это новое поле.

Проанализируем ситуацию: теперь для тех документов, у которых нет реквизита ИсточникФинансирования, поле примет значение "Не определено". Когда пользователь установит фильтр ИсточникДляОтбора Равно "ОМС", записи со значением "Не определено" законно не пройдут проверку и будут исключены из отчета.

Решение №3: Ограничение доступных типов в наборе данных

Еще один эффективный метод — это ручное ограничение типов в настройках поля СКД. Выясним, как это сделать:

На закладке Наборы данных найдите ваше составное поле (например, Реестр или Регистратор). В колонке Тип значения (или в свойствах поля на закладке "Роли") можно принудительно ограничить список допустимых типов только теми документами, у которых есть нужный реквизит. Если исключить из списка типы-пустышки, СКД перестанет игнорировать условия отбора, так как область поиска сузится до объектов с известной структурой.

Решение №4: Работа с расширением языка запросов {ГДЕ ...}

В тексте запроса автора темы используются фигурные скобки: {ГДЕ СпецРеестДанныеПоПациентам.Ссылка.* КАК Реестр}. Это мощный инструмент, который позволяет СКД динамически добавлять условия. Однако именно при использовании .* (обращение ко всем полям через точку) возникает путаница с составными типами в блоках ОБЪЕДИНИТЬ ВСЕ.

Чтобы избежать проблем в таких случаях, рекомендуется выносить поля, по которым планируется отбор, в список выбора каждой части объединения. Рассмотрим пример правильного структурирования:


ВЫБРАТЬ
    Т.Регистратор,
    Т.Регистратор.ИсточникФинансирования КАК ИсточникФин
ПОМЕСТИТЬ втДанные
ИЗ
    Документ.Реестр1 КАК Т
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
    Т2.Регистратор,
    NULL // Здесь явно указываем NULL, так как реквизита нет
ИЗ
    Документ.Реестр2 КАК Т2;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    втДанные.Регистратор,
    втДанные.ИсточникФин
ИЗ
    втДанные КАК втДанные
{ГДЕ
    втДанные.ИсточникФин}

Разберем, что мы сделали: мы заранее определили поле ИсточникФин. В тех ветках объединения, где реквизита нет, мы явно проставили NULL. Теперь для СКД это обычное поле с определенным типом (или NULL), и отбор по нему будет работать по классическим правилам логики, без "умных" исключений для отсутствующих метаданных.

Резюме

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

  1. Всегда используйте ВЫРАЗИТЬ, если точно знаете тип объекта в составном поле.
  2. При использовании ОБЪЕДИНИТЬ ВСЕ старайтесь приводить поля к единому виду в каждой части запроса.
  3. Для пользовательских отборов создавайте вычисляемые поля с функцией ЕСТЬNULL, чтобы превратить "отсутствие реквизита" в явное значение, которое можно отфильтровать.
  4. Проверяйте настройки "Доступные типы" в схеме компоновки, чтобы исключить заведомо неподходящие объекты.

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

← На главную