Как исправить ошибку «Несоответствие типов (параметр номер 1)» при левом соединении и настроить вывод нулевых значений в СКД 1С?

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

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

Выясним причину: почему возникает ошибка «Несоответствие типов»?

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

Проблема кроется в автоматической подстановке параметров в виртуальные таблицы (например, таблицы остатков или оборотов), когда эти таблицы участвуют в левом соединении. СКД видит пустые скобки параметров у виртуальной таблицы, например РегистрНакопления.ОбъемыРесурсовИС.Остатки(, ), и пытается самостоятельно спроецировать туда глобальные параметры периода (такие как &НачалоПериода, &КонецПериода или &Период).

Конфликт типов данных происходит по следующим причинам:

  1. Использование типа «СтандартныйПериод»: Если на форме отчета пользователь выбирает период через стандартный диалог, параметр СКД имеет тип СтандартныйПериод. Компоновщик пытается напрямую передать этот сложный объект в качестве первого параметра виртуальной таблицы остатков, которая ожидает строго тип Дата. Это мгновенно вызывает ошибку несоответствия типов в параметре №1.
  2. Запутанные связи при левом соединении: Когда виртуальная таблица соединяется левым соединением с другой таблицей, СКД не всегда может корректно определить, к какому именно полю или параметру привязать период, особенно если в запросе присутствует несколько пакетов или временных таблиц.

Рассмотрим подробнее три основных способа решения этой проблемы, начиная с архитектурно наиболее правильного.

Решение №1: Использование временных таблиц вместо левого соединения напрямую (Рекомендуемый подход)

В тексте запроса автора темы присутствует серьезная архитектурная ошибка — левое соединение выполняется непосредственно к виртуальной таблице остатков регистра накопления:


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

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

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

Шаг 1. Сначала выберем остатки в отдельную временную таблицу, передав параметры даты явно:


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

Шаг 2. Теперь в основном запросе выполним левое соединение уже с нашей подготовленной временной таблицей втОстаткиРесурсов:


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

Этот подход не только избавит вас от ошибок компоновки, но и существенно ускорит работу отчета на реальных базах данных.

Решение №2: Использование фигурных скобок (Расширение языка запросов СКД)

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

Посмотрим на пример явного указания параметров:

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

Решение №3: Разделение комплексного параметра «Период» в настройках СКД

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

Проанализируем схему настройки параметров в СКД:

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

Таким образом, пользователь будет видеть на форме только одно удобное поле для выбора периода, а виртуальные таблицы запроса будут получать на вход очищенные, готовые значения типа Дата, что исключит возникновение ошибки «Несоответствие типов».

Решение проблемы с «пустой ячейкой» вместо нуля при использовании функции ЕСТЬNULL

Теперь разберем второй вопрос автора: почему функция ЕСТЬNULL(МойДок.Остаток, 0) возвращает пустую ячейку в результирующей таблице вместо ожидаемого числового нуля?

Дело в том, что функция ЕСТЬNULL на уровне базы данных отрабатывает абсолютно корректно — она действительно возвращает физическое число 0 в тех строках, где значение отсутствовало (было равно NULL). Однако платформа 1С по умолчанию скрывает нулевые значения в табличных документах и экранных формах для повышения читаемости данных (чтобы отчет не выглядел «замусоренным» нулями).

Чтобы заставить систему принудительно выводить число «0», выполните следующие настройки формата вывода поля:

  1. В схеме компоновки данных (СКД) перейдите на вкладку Наборы данных.
  2. Найдите ваше поле (например, ФактОбъем или Остаток).
  3. В колонке Оформление нажмите кнопку выбора (три точки).
  4. В открывшемся окне параметров оформления найдите свойство Формат.
  5. В строке конструктора формата укажите параметр Представление нуля (код формата ЧН=0). Полная строка формата для числового поля с двумя знаками после запятой будет выглядеть так: ЧДЦ=2; ЧН=0.

Если вы выводите данные программно через код в обычную таблицу значений на форме, то аналогичное форматирование можно применить к колонке элемента формы (например, к элементу управления типа ПолеВвода или к колонке ТабличногоПоля), настроив свойство Формат аналогичной строкой: ЧДЦ=2; ЧН=0.

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

← На главную