Aggregates

COMP3311 20T3 ♢ Aggregates ♢ [0/10]
❖ Aggregates

Aggregates reduce a collection of values into a single result.

Examples:   count(Tuples),   sum(Numbers),   max(AnyOrderedType)

The action of an aggregate function can be viewed as:

State = initial state
for each item T {
    # update State to include T
    State = updateState(State, T)
}
return makeFinal(State)

COMP3311 20T3 ♢ Aggregates ♢ [1/10]
❖ Aggregates (cont)

Aggregates are commonly used with GROUP BY.

In that context, they "summarise" each group.

Example:

R               select a,sum(b),count(*)
 a | b | c      from R group by a
---+---+---
 1 | 2 | x       a | sum | count
 1 | 3 | y      ---+-----+-------
 2 | 2 | z       1 |   5 |     2
 2 | 1 | a       2 |   6 |     3
 2 | 3 | b

COMP3311 20T3 ♢ Aggregates ♢ [2/10]
❖ User-defined Aggregates

SQL standard does not specify user-defined aggregates.

But PostgreSQL provides a mechanism for defining them.

To define a new aggregate, first need to supply:

COMP3311 20T3 ♢ Aggregates ♢ [3/10]
❖ User-defined Aggregates (cont)

New aggregates defined using CREATE AGGREGATE statement:

CREATE AGGREGATE AggName(BaseType) (
    sfunc     = UpdateStateFunction,
    stype     = StateType,
    initcond  = InitialValue,
    finalfunc = MakeFinalFunction,
    sortop    = OrderingOperator
);

COMP3311 20T3 ♢ Aggregates ♢ [4/10]
❖ User-defined Aggregates (cont)

Example: defining the count aggregate (roughly)

create aggregate myCount(anyelement) (
    stype    = int,    -- the accumulator type
    initcond = 0,      -- initial accumulator value
    sfunc    = oneMore -- increment function
);

create function
    oneMore(sum int, x anyelement) returns int
as $$
begin return sum + 1; end;
$$ language plpgsql;

COMP3311 20T3 ♢ Aggregates ♢ [5/10]
❖ User-defined Aggregates (cont)

Example: sum2 sums two columns of integers

create type IntPair as (x int, y int);

create function
   addPair(sum int, p IntPair) returns int
as $$
begin return sum + p.x + p.y; end;
$$ language plpgsql;

create aggregate sum2(IntPair) (
   stype     = int,
   initcond  = 0,
   sfunc     = addPair
);

COMP3311 20T3 ♢ Aggregates ♢ [6/10]
❖ User-defined Aggregates (cont)

PostgreSQL has many aggregates (e.g. sum, count, ...)

But it doesn't have a product aggregate.

Implement a prod aggregate that

Usage:

select prod(*) from iota(5);
 prod 
------
  120

COMP3311 20T3 ♢ Aggregates ♢ [7/10]
❖ User-defined Aggregates (cont)

Example: product aggregate

create function
   mult(soFar numeric, next numeric) returns numeric
as $$
begin return soFar * next; end;
$$ language plpgsql;

create aggregate prod(numeric) (
   stype    = numeric,
   initcond = 1,
   sfunc    = mult
);

COMP3311 20T3 ♢ Aggregates ♢ [8/10]
❖ User-defined Aggregates (cont)

Define a concat aggregate that

Example:

select count(*), concat(name) from Employee;
-- returns e.g.
  count |         concat
 -------+----------------------
      4 | John,Jane,David,Phil

COMP3311 20T3 ♢ Aggregates ♢ [9/10]
❖ User-defined Aggregates (cont)

Example: string concatenation aggregate

create function
    join(s1 text, s2 text) returns text
as $$
begin
   if (s1 = '') then
      return s2;
   else
      return s1||','||s2;
   end if;
end;
$$ language plpgsql;

create aggregate concat(text) (
   stype    = text,
   initcond = '',
   sfunc    = join
);

COMP3311 20T3 ♢ Aggregates ♢ [10/10]


Produced: 15 Oct 2020