Перейти к основному содержимому
Версия: 4.x

Операции с множествами

Одной из ключевых возможностей платформы является возможность выполнения некоторых операций для всех наборов объектов, для которых значения одного или нескольких свойств не равны NULL. В логике свойств такой операцией является вычисление различных агрегирующих функций.

Агрегирующие функции

Агрегируюшая функция вычисляет на множестве наборов объектов некоторый результат в виде единичного объекта. Эта функция определяется начальным значением (как правило NULL), свойствами, которые она использует (операндами), операцией добавления к промежуточному результату текущих значений операндов, а также функцией преобразования промежуточного результата в конечный (как правило промежуточный результат и является конечным результатом).

Агрегирующая функция является коммутативной, если при вычислении результата не важно, в каком порядке перебираются наборы объектов исходного множества.

В таблице снизу представлены поддерживаемые на данный момент виды агрегирующих функций:

Вид / опция в инструкцииНачальное значениеНазв. операндовОперация добавленияФункция преобразованияКоммутативностьТип данных
SUMNULLoperandresult = result (+) operandresult+число
MAXNULLoperandresult = max(result, operand)result+любой сравнимый
MINNULLoperandresult = min(result, operand)result+любой сравнимый
CONCATNULLseparator, operandresult = CONCAT separator, result, operandresult-строковый
LAST / PREVNULLwhere, operandresult = IF where THEN operand ELSE resultresult-любой

С точки зрения определения множества наборов объектов, а также способа представления результата, можно выделить четыре основных оператора работы с множествами:

Корректность операции

Необходимо учитывать, что при выполнении каждой операции над множеством наборов объектов это множество должно быть конечным. В этом случае операцию будем называть корректной.

Примеры

CLASS A;
d = DATA INTEGER (A);

f (b) = GROUP SUM 1 IF d(a) < b;
messageF { MESSAGE f(5); } // успешно выполнится

g = GROUP SUM f(b);
messageG { MESSAGE g(); } // f(b) не NULL для бесконечного числа b, платформа выдаст ошибку

FORM f
OBJECTS d=DATE
;

printFWithD { PRINT f OBJECTS d=currentDate(); } // успешно выполнится

// фильтра для дат нет, а d IS DATE не NULL для бесконечного числа d, платформа выдаст ошибку
printFWithoutD { PRINT f; }

Существует несколько нетривиальных случаев, когда операция является корректной, но платформа не может это определить. Например, если единственным ограничивающим условием на параметр является вхождение его в диапазон:

hs = GROUP SUM 1 IF (a AS INTEGER) >= 4 AND a <= 6;
messageHS { MESSAGE hs(); } // теоретически должна выдать 3, но платформа все равно выдаст ошибку
// workaround: для работы с интервалами можно использовать свойство iterate
// (оно в свою очередь реализуется через рекурсию)
hi = GROUP SUM 1 IF iterate(a, 4, 6);