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