Почему в Конструкторе запросов 1С возникает ошибка «Несовместимые типы» при использовании «ПЕРИОДАМИ» и как её решить?

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

При разработке отчетов и обработок в платформе 1С часто возникает необходимость передать таблицу значений в запрос через параметр и получить итоговые данные, сгруппированные по временным интервалам (например, по месяцам). Однако при попытке настроить секцию ИТОГИ ПО ... ПЕРИОДАМИ(...) визуальный Конструктор запросов может выдать сообщение об ошибке: «Несовместимые типы».

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

Анализ ситуации и причины ошибки

Рассмотрим стандартный пример запроса, в который через параметр &Перемещения передается внешняя таблица значений. Запрос помещает данные во временную таблицу, после чего формирует выборку с итоговыми полями:


ВЫБРАТЬ
    Перемещения.Фамилия,
    Перемещения.Имя,
    Перемещения.Отчество,
    Перемещения.ДатаПриказа,
    Перемещения.НомерПриказа,
    Перемещения.Специальность,
    Перемещения.Должность,
    Перемещения.Подразделение,
    Перемещения.ДатаДвиженияДатой КАК ДатаДвиженияДатой
ПОМЕСТИТЬ ВТ_Перемещения
ИЗ
    &Перемещения КАК Перемещения
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_Перемещения.Фамилия,
    ВТ_Перемещения.Имя,
    ВТ_Перемещения.Отчество,
    ВТ_Перемещения.ДатаПриказа,
    ВТ_Перемещения.НомерПриказа,
    ВТ_Перемещения.Специальность,
    ВТ_Перемещения.Должность,
    ВТ_Перемещения.Подразделение,
    ВТ_Перемещения.ДатаДвиженияДатой КАК ДатаДвиженияДатой
ИЗ
    ВТ_Перемещения КАК ВТ_Перемещения
ИТОГИ ПО
    ДатаДвиженияДатой ПЕРИОДАМИ(МЕСЯЦ, , )

При попытке сохранить этот запрос по кнопке «ОК» в Конструкторе запросов возникает ошибка «Несовместимые типы».

Выясним причину такого поведения. Дело в том, что синтаксический анализатор Конструктора запросов работает в интерактивном режиме и не имеет доступа к метаданным внешней таблицы значений, передаваемой через параметр &Перемещения на этапе выполнения. Поскольку типы колонок таблицы-параметра заранее неизвестны Конструктору, встроенная проверка определяет тип поля ДатаДвиженияДатой как составной или неопределенный.

Конструкция ПЕРИОДАМИ требует строгого типа Дата. Так как Конструктор не может гарантировать тип поля, он блокирует сохранение предупреждением. Однако если в самом коде 1С перед передачей в запрос колонка таблицы значений имеет тип Дата, платформенный движок запросов без проблем выполнит данный текст.

Способы решения и альтернативные подходы

Проанализируем основные способы, позволяющие обойти эту проблему или корректно построить итоговые данные по периодам.

Способ 1. Игнорирование предупреждения Конструктора или ручной ввод

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

Способ 2. Явное задание типов в Таблице Значений

Чтобы избежать логических ошибок при выполнении, всегда типизируйте колонки таблицы значений при ее программном создании перед заполнением из файла (Excel, CSV и др.):


ТаблицаПеремещений = Новый ТаблицаЗначений;
ТаблицаПеремещений.Колонки.Добавить("Фамилия", Новый ОписаниеТипов("Строка"));
ТаблицаПеремещений.Колонки.Добавить("Имя", Новый ОписаниеТипов("Строка"));
ТаблицаПеремещений.Колонки.Добавить("ДатаДвиженияДатой", Новый ОписаниеТипов("Дата"));

Способ 3. Группировка через НАЧАЛОПЕРИОДА и СГРУППИРОВАТЬ ПО

Если вам необходима плоская таблица результатов без построения иерархического дерева итогов, рекомендуется отказаться от секции ИТОГИ в пользу стандартной функции НАЧАЛОПЕРИОДА и секции СГРУППИРОВАТЬ ПО. Этот вариант не вызывает никаких предупреждений в Конструкторе запросов:


ВЫБРАТЬ
    НАЧАЛОПЕРИОДА(ВТ_Перемещения.ДатаДвиженияДатой, МЕСЯЦ) КАК ПериодМесяц,
    ВТ_Перемещения.Подразделение КАК Подразделение,
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВТ_Перемещения.НомерПриказа) КАК КоличествоПриказов
ИЗ
    ВТ_Перемещения КАК ВТ_Перемещения
СГРУППИРОВАТЬ ПО
    НАЧАЛОПЕРИОДА(ВТ_Перемещения.ДатаДвиженияДатой, МЕСЯЦ),
    ВТ_Перемещения.Подразделение

Особенности обхода итогов по периодам

Рассмотрим важные нюансы работы с секцией ИТОГИ ПО ... ПЕРИОДАМИ в коде 1С:

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