Это вторая статья по аналитическим функциям. С первой статьёй можно познакомиться здесь - //infostart.ru/1c/articles/2238021/.
Постановка задачи.
Необходимо сравнить продажи менеджеров с значением продаж самого эффективного менеджера за месяц.
Исходные данные:

Результат на выходе:

select emp.name,
emp.val,
emp.месяц,
(select max(val) from employees where месяц = emp.месяц) max_val
from employees emp
Запрос не является оптимальным, поскольку в каждой строке запроса выполнятся дополнительный запрос ко всем данным в кадой строчке запроса. Кроме того, 1С не поддерживает подзапросы в разделе SELECT.
Использование аналитической функции:
Аналитические функции в SQL (также известные как оконные функции) — это инструменты для выполнения сложных вычислений на наборе строк, сохраняя при этом детализацию исходных данных. В отличие от агрегатных функций, которые группируют данные и возвращают одно значение для всей группы, аналитические функции возвращают отдельное значение для каждой строки в наборе.
select emp.name,
emp.val,
emp.месяц,
max(val) over (partition by месяц) max_val
from employees emp
1С не поддерживает аналитические функции, хотя на них в SQL сформировался свой стандарт.
Аналог аналитических функций в 1С
В 1С СКД есть свои аналитические функции: ВычислитьВыражение, ВычислитьВыражениеСГруппировкойМассив, ВычислитьВыражениеСГруппировкойТаблицаЗначений. Данные функции реализованы только в СКД и выполняются только после основного запроса. Фактически обработка данных производится на стороне сервера 1С, а не сервера баз данных.
Синтаксис функции «ВычислитьВыражениеСГруппировкойМассив»:
ВычислитьВыражениеСГруппировкойМассив (Выражение, ВыраженияПолейГруппировки, ОтборЗаписей, ОтборГруппировок).
Параметры:
- Выражение - выражение, которое нужно вычислить. Тип Строка. Например, "Сумма(СуммаОборот)";
- ВыраженияПолейГруппировки - выражения полей группировки, перечисленные через запятую. Например, "Контрагент, Партия";
- ОтборЗаписей - выражение, применяемое к детальным записям. Например, "ПометкаУдаления = Ложь". Если в данном параметре используется агрегатная функция, то при выполнении компоновки данных возникнет ошибка;
- ОтборГруппировок - отбор, применяемый к групповым записям. Например: "Сумма(СуммаОборот) > &Параметр1".
Как видим, синтаксис похож на синтаксис аналитической функции SQL.
Функция ВычислитьВыражениеСГруппировкойМассив позволят возвращать массив, каждый элемент которого содержит результат вычисления выражения для группировки по указанному полю. То есть массив вычисляемых полей.
ВЫБРАТЬ
ВременнаяТаблица.val КАК max_val,
ВременнаяТаблица.name КАК max_name,
ВременнаяТаблица2.val КАК val,
ВременнаяТаблица2.name КАК name,
ВременнаяТаблица2.Month КАК Month
ИЗ
ВременнаяТаблица КАК ВременнаяТаблица2
ЛЕВОЕ СОЕДИНЕНИЕ ВременнаяТаблица КАК ВременнаяТаблица
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВременнаяТаблица КАК ВременнаяТаблица1
ПО ВременнаяТаблица.Month = ВременнаяТаблица1.Month
ПО ВременнаяТаблица2.Month = ВременнаяТаблица.Month
СГРУППИРОВАТЬ ПО
ВременнаяТаблица.name,
ВременнаяТаблица.val,
ВременнаяТаблица2.Month,
ВременнаяТаблица2.val,
ВременнаяТаблица2.name
ИМЕЮЩИЕ
МАКСИМУМ(ВременнаяТаблица1.val) = ВременнаяТаблица.val
УПОРЯДОЧИТЬ ПО
Month
ВЫБРАТЬ
ВременнаяТаблица.val КАК val,
ВременнаяТаблица.name КАК name,
ВременнаяТаблица.Month КАК Month
ПОМЕСТИТЬ ВременнаяТаблица1
ИЗ
ВременнаяТаблица КАК ВременнаяТаблица
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВременнаяТаблица КАК ВременнаяТаблица1
ПО ВременнаяТаблица.Month = ВременнаяТаблица1.Month
СГРУППИРОВАТЬ ПО
ВременнаяТаблица.Month,
ВременнаяТаблица.name,
ВременнаяТаблица.val
ИМЕЮЩИЕ
МАКСИМУМ(ВременнаяТаблица1.val) = ВременнаяТаблица.val
условие ИМЕЮЩИЕ МАКСИМУМ(ВременнаяТаблица1.val) = ВременнаяТаблица. val
ищет максимальное значение val за месяц.
Если заменить это условие на ИМЕЮЩИЕ МИНИМУМ (ВременнаяТаблица1.val) = ВременнаяТаблица. val
то получим минимальное значение за месяц.
ЛЕВОЕ СОЕДИНЕНИЕ ВременнаяТаблица КАК ВременнаяТаблица ПО ВременнаяТаблица.месяц = ВременнаяТаблица1.месяц
создаёт окно просмотра.
Такая конструкция позволяет не только получить максимальное значение val за месяц, но и сразу узнать какому сотруднику оно принадлежит. Для аналитической функции SQL необходимо будет использовать два выражния.
Усложним условие.
Предположим за третий месяц два сотрудника продали товара на одинаковую сумму, для этого добавим во временную таблицу, формирующую исходные данные, ещё одно объединение:
Фактически, мы получили аналог работы с классическим регистром сведений, где ресурсами являются месяц и сотрудник, а измерением сумма продаж.
Примеры применения запроса.
- Сравнение производительности сотрудников (подразделений).
- Сравнение прибыли (расходов) по месяцам с прибылью максимально эффективного месяца.
- Вычисление максимального (минимального) стажа по специальностям.
- Определение контрагента с максимальной задолженностью.
- …
Ссылки на другие статьи автора по теме запросов SQL на инфостарте.
Преобразование в запросе строки в дату одним выражением - //infostart.ru/1c/articles/1567059/ .
Запрос, получающий изменения ресурса в регистрах сведений по датам изменения за период - //infostart.ru/1c/articles/1041396/
Генерация ряда дат и данные из периодических регистров на каждый день - //infostart.ru/1c/articles/1012148/ .
Срез последних - аналог запроса - //infostart.ru/1c/articles/980323/.
Вступайте в нашу телеграмм-группу Инфостарт