Für gezielte Datenbankexporte oder -views möchte man oft eine Zeile für einen Eintrag in der SQL Abfrage erhalten. Beim Verknüpfen von mehreren Tabellen führt dies bei 1:n oder n:m Beziehungen zu dem Nachteil, dass für die Basistabelle mehrere Zeilen entstehen. Zur Verdeutlichung sei folgendes Beispiel (in PostgreSQL) gegeben:
create table account (
ID BIGINT not null,
EMAIL CHARACTER VARYING(1024) not null unique,
primary key (ID)
);
create table history (
ID BIGINT not null,
ACCOUNT_FK BIGINT not null,
ENTRY CHARACTER VARYING(1024) not null unique,
primary key (ID)
);
Ziel soll es sein, ein Abfrage zu erstellen, die alle Accounts und die dazu zugehörigen Historyeinträge zurückliefert. Allerdings soll pro Account nur eine Zeile verwendet werden.
Folgende Abfrage führt nicht zum Ziel:
select account.email, history.entry
from account, history
where account.id = history.account_fk;
Eine Möglichkeit ist es, die Einträge in der History zu verknüpfen, z. B. über ein concat Funktion. Wenn diese als Aggregatfunktion zur Verfügung steht, kann diese in einem group by verwendet werden.
In PostgreSQL ist dies wie folgt möglich:
CREATE AGGREGATE textcat_all(
basetype = text,
sfunc = textcat,
stype = text,
initcond = ''
);
Mit folgender Abfrage kommt man dann zu dem Ziel nur noch eine Zeile pro Account zu erhalten:
select account.email, textcat_all(history.entry || ',')
from account, history
where account.id = history.account_fk;
group by account.email
(Siehe dazu auch hier http://archives.postgresql.org/pgsql-novice/2003-09/msg00177.php)
In mysql ist dies noch einfacher, denn hier existiert bereits eine solche Aggregationsfunktion: http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat