Skip to content

Aggregation

Leon Starr edited this page Nov 6, 2023 · 2 revisions

Aggregation is some operation that can be applied to a set of scalar values of the same type yielding a single scalar value result. For example, the sum operation adds up all of the scalar values in a column. Other common possibilities are min, max and avg (average). Aggregation is not a relational operation since it yields a scalar value rather than a relation.

So it is critical that any given aggregation operation be supported by the type it operates on. It makes no sense, for example, to take the average of a set of values of type Name since that type does not support addition. Many aggregation operations require at least one input value so, to avoid a run-time error, you must check for the empty set.

Scrall does not provide a predefined list of aggregation operations. These must be defined (or supplied automatically) as part of the type definition system since that is where supported operations are managed. Scrall merely provides a syntax for invoking an aggregation function on an attribute or table column.

Assuming an avg aggregation operation has been defined and is supported on the Altitude type, as one would expect since Altitude would be based on the Rational type, this works:

avg altitude = Aircraft(*).(Altitude).avg() // same result

When the dot notation is a suffix to a projection expression on one or more attributes it must designate an aggregation.

Since there is only one attribute, it can be shortened to get the same result since all attributes and all instances are implied:

avg altitude = Aircraft.Altitude.avg()

If there are zero instances of Aircraft, the assignment will fail with a run-time error since avg would need to divide by zero and min and max are not defined for empty sets. (You CAN define max so that it approximates negative infinity as the minimum system defined value, but it’s unclear that this would be useful). So, if you are not certain to obtain at least one instance with an aggregation operation that isn’t defined on the empty set, check first as shown:

Aircraft? avg altitude = Aircraft.Altitude.avg()

Above, we create a boolean condition as indicated by the ? symbol on the right of an implicit “select all” on Aircraft. If at least one is found, the average is computed. (Technically we need only do an Aircraft(1) select, but we’ll assume that the code generation is smart enough to figure this out since the selection is not assigned and merely tested).

To produce a table of heading and altitude averages, do this:

Aircraft? ha avgs #= Aircraft.(Heading, Altitude).avg()

To get the maximum altitude of all aircraft faster than a certain speed:

Aircraft? highfast alt = Aircraft( Airspeed > s ).Altitude.max()

Since there is a max symbol defined, you can do this which produces the same result:

Aircraft? highfast alt = Aircraft(1, Airspeed > s, +^Altitude).Altitude

You can specify an operation on the projected attribute as input into the aggregation like this:

totalCapacity = Duty Station.(Capacity * scale).sum()

Introduction

Model semantics

Flows (as Variables)

Constants and literals

Structure of an activity

Accessing the class model

Data flow


Grammar and parsing notes

Components

Clone this wiki locally