# DeAL TutorialUser-Defined Aggregates

### User-Defined Aggregates (.deal | .fac)

The user can define a new aggregate, called `newaggr`, by writing the rules that support:

single(newaggr, Y, NV)

and

multi(newaggr, Y, OV, NV)

where

`single`is the computation to be performed on a singleton set having`Y`as its only element.`multi`denotes how to compute the aggregate value`NV`for a set S' obtained by adding a new element`Y`to the the set S, where the value of the aggregate for S is`OV`.

For instance, if we had to define the `max` aggregate we would write:

single(max, Y, Y). multi(max, Y, MO, MN) <- Y > MO, MN = Y. multi(max, Y, MO, MN) <- Y <= MO, MN = MO.

Likewise, in DeAL, `count` and `sum` could have been defined as shown by the two pairs of rules below:

single(count, Y, 1). multi(count, Y, Old, New) <- New = Old + 1. single(sum, Y, Y). multi(sum, Y, Old, New) <- New = Old + Y.

The `count` and `sum` so defined behave as `count_all` and `sum_all` since these rules accumulate the `Old` value
with the new `Y`, without checking whether the same `Y` value had already occurred.

User-defined aggregates can also be called by means of `aggr` goals. In this case, when applied to the empty set, the compiler will
search for an `empty` rule defining the behavior of that particular aggregate on an empty
set. For instance, the built-in aggregates behave as if they were defined by the following rules:

empty(sum, 0). empty(count, 0). empty(max, 0) <- false.

On empty set, `aggr` will return `0` for sum and count, and will fail on max (also fails on min and avg).

Several new aggregates can be defined using the single and multi
rules. For instance in SQL, after the maximum is found, a second
sub-query is needed to return all the values associated with the
maximum. In DeAL, if `sppp` denotes a supplier-part-price relation, to find, for each supplier
their most expensive items and their common price of these items, we
can write:

findmax(S, mymax<(Itm, Pric)>) <- sppp(S, Itm, Pric). single(mymax, (Item, Pr), (Item, Pr)). multi(mymax, (Sit, Sp), (Oit, Op), (Sit, Sp)) <- Sp >= Op. multi(mymax, (Sit, Sp), (Oit, Op), (Oit, Op)) <- Sp < Op.

This example illustrates that:

- Aggregates can return full tuples, such as the pair
`(Item, Pr)`produced by`mymax` - More than one value/tuple can be returned from the computation of an aggregate.