При разработке отчетов и обработок в платформе 1С часто возникает необходимость передать таблицу значений в запрос через параметр и получить итоговые данные, сгруппированные по временным интервалам (например, по месяцам). Однако при попытке настроить секцию ИТОГИ ПО ... ПЕРИОДАМИ(...) визуальный Конструктор запросов может выдать сообщение об ошибке: «Несовместимые типы».
Разберем подробно причину такого поведения визуального редактора, выясним, почему запрос при этом может успешно работать в коде, и проанализируем альтернативные способы построения итогов по периодам.
Рассмотрим стандартный пример запроса, в который через параметр &Перемещения передается внешняя таблица значений. Запрос помещает данные во временную таблицу, после чего формирует выборку с итоговыми полями:
ВЫБРАТЬ
Перемещения.Фамилия,
Перемещения.Имя,
Перемещения.Отчество,
Перемещения.ДатаПриказа,
Перемещения.НомерПриказа,
Перемещения.Специальность,
Перемещения.Должность,
Перемещения.Подразделение,
Перемещения.ДатаДвиженияДатой КАК ДатаДвиженияДатой
ПОМЕСТИТЬ ВТ_Перемещения
ИЗ
&Перемещения КАК Перемещения
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ_Перемещения.Фамилия,
ВТ_Перемещения.Имя,
ВТ_Перемещения.Отчество,
ВТ_Перемещения.ДатаПриказа,
ВТ_Перемещения.НомерПриказа,
ВТ_Перемещения.Специальность,
ВТ_Перемещения.Должность,
ВТ_Перемещения.Подразделение,
ВТ_Перемещения.ДатаДвиженияДатой КАК ДатаДвиженияДатой
ИЗ
ВТ_Перемещения КАК ВТ_Перемещения
ИТОГИ ПО
ДатаДвиженияДатой ПЕРИОДАМИ(МЕСЯЦ, , )
При попытке сохранить этот запрос по кнопке «ОК» в Конструкторе запросов возникает ошибка «Несовместимые типы».
Выясним причину такого поведения. Дело в том, что синтаксический анализатор Конструктора запросов работает в интерактивном режиме и не имеет доступа к метаданным внешней таблицы значений, передаваемой через параметр &Перемещения на этапе выполнения. Поскольку типы колонок таблицы-параметра заранее неизвестны Конструктору, встроенная проверка определяет тип поля ДатаДвиженияДатой как составной или неопределенный.
Конструкция ПЕРИОДАМИ требует строгого типа Дата. Так как Конструктор не может гарантировать тип поля, он блокирует сохранение предупреждением. Однако если в самом коде 1С перед передачей в запрос колонка таблицы значений имеет тип Дата, платформенный движок запросов без проблем выполнит данный текст.
Проанализируем основные способы, позволяющие обойти эту проблему или корректно построить итоговые данные по периодам.
Если вы уверены, что в исходную таблицу значений передаются строго даты, вы можете оставить текст запроса с предложением ПЕРИОДАМИ(МЕСЯЦ, , ). Вы можете отредактировать текст запроса непосредственно в коде модуля без использования Конструктора. При вызове метода Запрос.Выполнить() платформа отработает корректно.
Чтобы избежать логических ошибок при выполнении, всегда типизируйте колонки таблицы значений при ее программном создании перед заполнением из файла (Excel, CSV и др.):
ТаблицаПеремещений = Новый ТаблицаЗначений;
ТаблицаПеремещений.Колонки.Добавить("Фамилия", Новый ОписаниеТипов("Строка"));
ТаблицаПеремещений.Колонки.Добавить("Имя", Новый ОписаниеТипов("Строка"));
ТаблицаПеремещений.Колонки.Добавить("ДатаДвиженияДатой", Новый ОписаниеТипов("Дата"));
Если вам необходима плоская таблица результатов без построения иерархического дерева итогов, рекомендуется отказаться от секции ИТОГИ в пользу стандартной функции НАЧАЛОПЕРИОДА и секции СГРУППИРОВАТЬ ПО. Этот вариант не вызывает никаких предупреждений в Конструкторе запросов:
ВЫБРАТЬ
НАЧАЛОПЕРИОДА(ВТ_Перемещения.ДатаДвиженияДатой, МЕСЯЦ) КАК ПериодМесяц,
ВТ_Перемещения.Подразделение КАК Подразделение,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВТ_Перемещения.НомерПриказа) КАК КоличествоПриказов
ИЗ
ВТ_Перемещения КАК ВТ_Перемещения
СГРУППИРОВАТЬ ПО
НАЧАЛОПЕРИОДА(ВТ_Перемещения.ДатаДвиженияДатой, МЕСЯЦ),
ВТ_Перемещения.Подразделение
Рассмотрим важные нюансы работы с секцией ИТОГИ ПО ... ПЕРИОДАМИ в коде 1С:
ПЕРИОДАМИ(МЕСЯЦ, ДатаНачала, ДатаОкончания) может автоматический дополнять временной ряд месяцами, в которых не было движения. Однако чтобы получить эти «пустые» периоды при обходе выборки во встроенном языке, в метод Выбрать() необходимо передать третьим параметром строку "ВСЕ":
ВыборкаПериод = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам, "ДатаДвиженияДатой", "ВСЕ");
Пока ВыборкаПериод.Следующий() Цикл
// Обработка каждого месяца, включая пустые
КонецЦикла;
"ВСЕ" не указать, пустые интервалы будут пропущены при обходе.
ИТОГИ предназначена для расчета агрегатных показателей (СУММА, КОЛИЧЕСТВО и др.). Если ресурсовые поля не указаны, предложение ИТОГИ сформирует лишь группировочную иерархию (дерево) без числовых подсумков.