При разработке отчетов на Системе компоновки данных (СКД) программисты часто сталкиваются с задачей получения статистических показателей по объектам, которые сами по себе не являются числами. Например, нужно посчитать среднее количество пациентов на одну болезнь или среднее количество документов на одного контрагента. Попытка использовать стандартную функцию Среднее() к полю типа Ссылка напрямую приводит к ошибке «Неверные параметры AVG», так как СУБД не может вычислить арифметическое среднее от уникального идентификатора (GUID).
В этой статье мы подробно разберем, как обойти это ограничение, правильно настроить ресурсы и корректно обработать ситуацию, когда в запросе присутствуют табличные части, вызывающие «размножение» строк.
Функция Среднее() в СКД на уровне запроса транслируется в SQL-агрегат AVG. Этот агрегат предназначен исключительно для числовых типов данных (целые, дробные). Поле Ссылка — это объектный тип. Чтобы получить «среднее количество», нам нужно сначала превратить ссылки в числа (посчитать их количество), а затем уже вычислять среднее от этих количеств по определенным группировкам.
Если ваша задача — получить количество уникальных пациентов в разрезе болезней, первым делом необходимо правильно настроить ресурс. Рассмотрим ситуацию: у одного пациента (одна ссылка) может быть несколько симптомов из табличной части. Если просто соединить документы с их табличными частями в запросе, количество строк увеличится, и обычное Количество(Ссылка) выдаст неверный результат.
Проанализируем правильный подход к настройке ресурса:
Ссылка (или его псевдонима КолБольных) в колонке «Выражение» напишем:
Количество(Различные Ссылка)Когда нам нужно получить именно «среднее от количества» (например, среднее число больных по разным типам болезней), мы сталкиваемся с необходимостью агрегации над уже агрегированными данными. В СКД для этого существует мощный механизм функций языка выражений.
Рассмотрим по шагам, как настроить расчет среднего количества больных по группировкам:
Среднее(ВычислитьВыражениеСГруппировкойМассив("Количество(Различные Ссылка)", "ТипБолезни"))
Количество(Различные Ссылка) — считает уникальных больных внутри каждой группы.ВычислитьВыражениеСГруппировкойМассив — собирает эти количества по всем «Типам болезней» в массив.Среднее() — вычисляет среднее арифметическое из полученного массива чисел.Важный нюанс: если вы хотите, чтобы отчет был гибким и не зависел от жестко прописанного имени группировки ("ТипБолезни"), можно использовать в качестве второго параметра пустую строку или системные поля, но чаще всего среднее требуется в конкретном контексте (например, среднее по больницам), поэтому указание измерения оправдано.
Этот метод часто называют «методом весов». Он позволяет превратить каждую уникальную запись в числовую единицу еще на этапе формирования набора данных.
Проанализируем ситуацию подробнее:
1 КАК ИндексОбъекта.Сумма(ИндексОбъекта), а выражение:
Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(ИндексОбъекта)", "Ссылка"))
Максимум), а затем просуммируем эти единицы по всем документам. Полученное число уже можно использовать в стандартных функциях Среднее() в вышестоящих итогах.Как отмечалось в сообщениях форума, часто проблема «неверного среднего» кроется в том, что данные из шапки документа (Тип болезни, Больница) дублируются столько раз, сколько строк в табличной части (Симптомы).
Для решения этой проблемы без использования сложных функций в ресурсах рекомендуется разделить наборы данных:
Ссылка.Если при выводе среднего и количества у вас появляются пустые строки (когда группировка по симптому есть, а самого симптома в документе нет), воспользуйтесь настройками отбора в СКД. Рассмотрим, как это сделать:
Симптом Заполнено.Используя данные методы, вы сможете строить сложную аналитическую отчетность в 1С, оперируя средними значениями даже для тех данных, которые изначально не являются числами.