При разработке сложных отчетов в системе компоновки данных (СКД), особенно в конфигурациях типа Управление торговлей 11.4 или ERP, программисты часто сталкиваются с ситуацией, когда необходимо объединить данные о продажах и их себестоимость из разных регистров. Одной из самых коварных ошибок в этом процессе является «Несоответствие типов (Параметр номер "1")» при обращении к виртуальным таблицам, таким как СрезПоследних. Рассмотрим подробно причины возникновения этой ошибки и разберем эффективные методы оптимизации производительности таких отчетов. В качестве практического примера реализации подобных задач доступен готовый отчет на СКД по двум регистрам накопления для УТ 11.5.
Ошибка в параметре №1 виртуальной таблицы СрезПоследних чаще всего связана с тем, как СКД передает значения из одного набора данных в другой через механизм связей. Рассмотрим ситуацию: у нас есть первый набор данных (Продажи), из которого мы получаем дату совершения операции, и второй набор данных (Себестоимость), который должен получить эту дату в качестве параметра Период.
Проанализируем типичные причины сбоя:
Регистратор.Дата) оказывается пустым, СКД пытается передать NULL в параметр Период виртуальной таблицы. Виртуальная таблица ожидает тип Дата и, получая NULL, выдает ошибку несоответствия типов.Регистратор.Дата), не всегда корректно типизируются системой при передаче между наборами.&ДатаСреза), система требует его заполнения еще до начала обработки связей.Первым делом нам необходимо сделать параметры виртуальной таблицы «гибкими» для СКД. Для этого в тексте запроса второго набора данных следует использовать расширение языка запросов СКД — фигурные скобки. Вместо жесткого указания параметра в скобках виртуальной таблицы, мы указываем его следующим образом:
ВЫБРАТЬ
СтоимостьТоваровСрезПоследних.АналитикаУчетаНоменклатуры.Номенклатура КАК Номенклатура,
СтоимостьТоваровСрезПоследних.Стоимость + СтоимостьТоваровСрезПоследних.СтоимостьДопРасходы КАК Себестоимость
ИЗ
РегистрСведений.СтоимостьТоваров.СрезПоследних({&ДатаСреза}, ) КАК СтоимостьТоваровСрезПоследних
Важный нюанс: В настройках связей наборов данных на вкладке «Связи наборов данных» убедимся, что мы передаем дату из первого набора именно в параметр ДатаСреза. Чтобы избежать проблем с NULL, в выражении источника связи рекомендуется использовать функцию ЕСТЬNULL. Пропишем выражение связи для даты:
ЕСТЬNULL(РегистраторДата, ДАТАВРЕМЯ(1, 1, 1))
Также в первом наборе данных заменим обращение Регистратор.Дата на стандартное поле Период или ПериодСекунда, если используется периодичность «Запись». Это не только повысит надежность, но и положительно скажется на скорости выполнения запроса, так как системе не придется делать лишнее соединение с таблицей регистраторов.
Даже если мы избавимся от ошибки типизации, мы можем столкнуться с тем, что отчет формируется крайне медленно (эффект «бесконечного» выполнения). Выясним причину: при связи двух наборов данных СКД выполняет запрос ко второму набору для каждой строки первого набора. Если в продажах 1000 строк, система сделает 1000 отдельных обращений к таблице СрезПоследних. Это классическая проблема производительности. Для решения подобных проблем со скоростью формирования отчетов в системе компоновки данных можно применить альтернативный метод оптимизации и ускорения выполнения отчетов в 1С.
Рассмотрим способы оптимизации:
ВыручкаИСебестоимостьПродаж уже содержит данные о себестоимости. Вместо того чтобы лезть в СтоимостьТоваров, проанализируем возможности основного регистра.СрезомПоследних внутри запроса по условию даты — задача нетривиальная и часто требует использования временных таблиц.В контексте УТ 11.4 для получения данных о продажах и себестоимости мы рекомендуем использовать следующий подход в рамках одного запроса. Это позволит избежать ошибок связи и обеспечит мгновенное формирование отчета:
ВЫБРАТЬ
ВыручкаОбороты.Склад КАК Склад,
ВыручкаОбороты.АналитикаУчетаНоменклатуры.Номенклатура КАК Номенклатура,
ВыручкаОбороты.КоличествоОборот КАК Продажи,
ВыручкаОбороты.СуммаВыручкиОборот КАК СуммаПродажи,
// Себестоимость берем напрямую из этого же регистра
ВыручкаОбороты.СтоимостьОборот + ВыручкаОбороты.СтоимостьДопРасходовОборот КАК Себестоимость
ИЗ
РегистрНакопления.ВыручкаИСебестоимостьПродаж.Обороты(&НачалоПериода, &КонецПериода, Авто, ) КАК ВыручкаОбороты
Если же ваша задача — вывести текущую себестоимость остатков рядом с продажами, то связь наборов данных по дате регистратора будет логически неверной, так как она покажет себестоимость на момент каждой конкретной продажи в прошлом. В этом случае правильнее будет связать продажи с текущим срезом последних (на фиксированную дату конца периода), передав параметр даты один раз, а не для каждой строки.
Проанализировав ситуацию, подведем итог правильной настройки сложного отчета в СКД:
NULL перед передачей в параметры связи.{} в параметрах виртуальных таблиц для их динамического заполнения компоновщиком.Период вместо обращения к реквизитам через точку (Регистратор.Дата).НачалоПериода и КонецПериода заполнены корректно (например, через функцию КонецПериода(&Дата, "День")).Соблюдение этих правил позволит вам создавать стабильные и быстрые отчеты, избегая трудноуловимых ошибок типизации и проблем с производительностью базы данных. Для поддержания стабильности системы и защиты данных при отладке сложных запросов используется автоматическое архивирование и тестирование баз 1С.