При разработке отчетов в Системе Компоновки Данных (СКД) начинающие программисты часто сталкиваются с ситуацией, когда запрос прекрасно работает в Консоли запросов для управляемых форм, но при запуске отчета в режиме "Предприятие" выдает ошибку: "Несоответствие типов (Параметр номер '1')" — для отладки и тестирования удобнее использовать универсальную консоль запросов и консоль СКД. В этой статье мы подробно разберем причины возникновения этой ошибки на примере соединения товарных запасов с ценами, проанализируем архитектурные ошибки запроса и составим правильный алгоритм решения.
Рассмотрим ситуацию, с которой столкнулся автор. Имеется задача: вывести остатки и обороты товаров по складам и присоединить к ним актуальную цену. Используя методики для быстрого анализа данных, исходный текст запроса выглядел следующим образом:
ВЫБРАТЬ
...
ИЗ
РегистрНакопления.ЗапасыНаСкладах.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Регистратор, , ) КАК ЗапасыНаСкладахОстаткиИОбороты,
РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, ВидЦен = &ВидЦен) КАК ЦеныНоменклатурыСрезПоследних
ГДЕ
ЗапасыНаСкладахОстаткиИОбороты.Номенклатура = ЦеныНоменклатурыСрезПоследних.Номенклатура
При выполнении этого кода возникает ошибка несоответствия типов в параметре номер 1. Давайте разберем, почему это происходит и какие еще критические ошибки допущены в этом запросе.
Сообщение об ошибке "Несоответствие типов (Параметр номер '1')" прямо указывает на то, что в первый параметр одной из виртуальных таблиц передается значение неверного типа. Часто такие проблемы выявляются при использовании инструментов анализа конфигураций, отчетов и обработок на наличие ошибок.
Давайте посмотрим на синтаксис виртуальной таблицы РегистрСведений.СрезПоследних. Она принимает параметры в следующем порядке:
Дата) — момент времени, на который нужно получить срез.В СКД есть механизм автозаполнения параметров. Если в настройках компоновки данных (на закладке "Параметры") у вас создан параметр "Период" с типом СтандартныйПериод (содержащий дату начала и дату окончания), а в запросе параметр для виртуальной таблицы не указан явно, СКД может попытаться подставить туда доступное значение.
Проблема возникает, когда система пытается "впихнуть" СтандартныйПериод или Неопределено туда, где ожидается конкретная Дата. В консоли запросов вы обычно вручную задаете параметры, поэтому там ошибка не воспроизводится. В СКД же управление параметрами сложнее.
Ошибка автора: Автор пытался исправить ситуацию, прописав &НачалоПериода, &КонецПериода внутри скобок СрезПоследних. Это вызвало синтаксическую ошибку, так как таблица ожидает только одну дату в первом параметре.
Помимо ошибки с типами, в запросе используется устаревший и опасный метод соединения таблиц — неявное соединение через запятую в секции ИЗ.
ИЗ
Таблица1,
Таблица2
ГДЕ
Таблица1.Поле = Таблица2.Поле
В языке запросов 1С (как и в стандартном SQL) такая конструкция сначала создает Декартово произведение. Это значит, что каждая строка первой таблицы соединяется с каждой строкой второй таблицы. Это серьезно влияет на производительность, а вопросы оптимизации отчетов с набором данных показывают, что такие запросы могут привести к критическим нагрузкам — выявить подобные проблемы на сервере поможет монитор производительности и анализа неоптимальных запросов.
Это приводит к:
ГДЕ написано с ошибкой.ВНУТРЕННЕЕ) строка с остатком товара просто исчезнет из отчета.Чтобы исправить ошибку и оптимизировать запрос, нам нужно выполнить два действия: использовать явное соединение и корректно передать параметр периода.
В отчетах по остаткам нам важно видеть товар, даже если на него не установлена цена. Для этого идеально подходит оператор ЛЕВОЕ СОЕДИНЕНИЕ. Главной таблицей будет таблица остатков, а таблицу цен мы будем "присоединять" к ней.
Для таблицы ОстаткиИОбороты нам нужен период (начало и конец). Для таблицы СрезПоследних нам нужна одна конкретная дата. Обычно, если мы смотрим отчет за период, цену логично брать либо на конец этого периода, либо на текущий момент. В данном случае будем использовать дату окончания отчета — &КонецПериода.
Рассмотрим итоговый правильный текст запроса:
ВЫБРАТЬ
ЗапасыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура,
ЗапасыНаСкладахОстаткиИОбороты.КоличествоНачальныйОстаток КАК КоличествоНачальныйОстаток,
ЗапасыНаСкладахОстаткиИОбороты.КоличествоПриход КАК КоличествоПриход,
ЗапасыНаСкладахОстаткиИОбороты.КоличествоРасход КАК КоличествоРасход,
ЗапасыНаСкладахОстаткиИОбороты.КоличествоКонечныйОстаток КАК КоличествоКонечныйОстаток,
ЗапасыНаСкладахОстаткиИОбороты.Организация КАК Организация,
ЗапасыНаСкладахОстаткиИОбороты.СтруктурнаяЕдиница КАК СтруктурнаяЕдиница,
ЗапасыНаСкладахОстаткиИОбороты.Регистратор КАК Регистратор,
ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0) КАК Цена
ИЗ
РегистрНакопления.ЗапасыНаСкладах.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Регистратор, , ) КАК ЗапасыНаСкладахОстаткиИОбороты
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&КонецПериода, ВидЦен = &ВидЦен) КАК ЦеныНоменклатурыСрезПоследних
ПО ЗапасыНаСкладахОстаткиИОбороты.Номенклатура = ЦеныНоменклатурыСрезПоследних.Номенклатура
Обратите внимание на конструкцию СрезПоследних(&КонецПериода, ...). Мы явно сказали системе: "Дай мне цены, актуальные на момент окончания отчета". Теперь СКД не будет пытаться подставить туда непонятные значения, и ошибка "Несоответствие типов" исчезнет.
Теперь запрос выполняется оптимально. Система берет таблицу остатков и ищет соответствия в таблице цен. В более сложных архитектурных задачах иногда требуется даже использование двух разных схем в отчете СКД, но для данной задачи достаточно правильного соединения.
Добавлена функция ЕСТЬNULL(..., 0). Это хорошая практика. Если соединение не нашло цену, пользователь увидит в отчете "0", а не пустую ячейку.
После исправления текста запроса, зайдите на вкладку "Параметры" в схеме компоновки данных. Убедитесь в следующем:
НачалоПериода и КонецПериода имеют тип Дата.НачалоПериода и КонецПериода пропишите соответственно:
&Период.ДатаНачала
&Период.ДатаОкончания
Период установите галочку "Ограничение доступности", если не хотите, чтобы пользователь видел технические даты.Соблюдение этих правил гарантирует стабильную работу отчета и корректное отображение данных без ошибок несоответствия типов.