PostgreSQL 9.0 oder höher:
Neuere Versionen von Postgres (seit Ende 2010) verfügen über die string_agg(expression, delimiter)
Funktion, die genau das tut, wonach die Frage gestellt wurde, und Sie können sogar die Trennzeichenfolge angeben:
SELECT company_id, string_agg(employee, ', ')
FROM mytable
GROUP BY company_id;
Postgres 9.0 hat außerdem die Möglichkeit hinzugefügt, eine ORDER BY
Klausel in einem beliebigen aggregierten Ausdruck anzugeben . Andernfalls ist die Reihenfolge undefiniert. So können Sie jetzt schreiben:
SELECT company_id, string_agg(employee, ', ' ORDER BY employee)
FROM mytable
GROUP BY company_id;
Oder in der Tat:
SELECT string_agg(actor_name, ', ' ORDER BY first_appearance)
PostgreSQL 8.4 oder höher:
PostgreSQL 8.4 (2009) führte die Aggregatfunktion ein,array_agg(expression)
die die Werte zu einem Array verkettet. Dann array_to_string()
kann das gewünschte Ergebnis erzielt werden:
SELECT company_id, array_to_string(array_agg(employee), ', ')
FROM mytable
GROUP BY company_id;
string_agg
für Versionen vor 8.4:
Falls jemand auf der Suche nach einem kompatiblen Shim für Datenbanken vor 9.0 darauf stößt, ist es möglich, alles string_agg
außer der ORDER BY
Klausel zu implementieren .
Mit der folgenden Definition sollte dies also genauso funktionieren wie in einer 9.x Postgres-Datenbank:
SELECT string_agg(name, '; ') AS semi_colon_separated_names FROM things;
Dies ist jedoch ein Syntaxfehler:
SELECT string_agg(name, '; ' ORDER BY name) AS semi_colon_separated_names FROM things;
--> ERROR: syntax error at or near "ORDER"
Getestet auf PostgreSQL 8.3.
CREATE FUNCTION string_agg_transfn(text, text, text)
RETURNS text AS
$$
BEGIN
IF $1 IS NULL THEN
RETURN $2;
ELSE
RETURN $1 || $3 || $2;
END IF;
END;
$$
LANGUAGE plpgsql IMMUTABLE
COST 1;
CREATE AGGREGATE string_agg(text, text) (
SFUNC=string_agg_transfn,
STYPE=text
);
Benutzerdefinierte Variationen (alle Postgres-Versionen)
Vor 9.0 gab es keine integrierte Aggregatfunktion zum Verketten von Zeichenfolgen. Die einfachste benutzerdefinierte Implementierung (unter anderem von Vajda Gabo in diesem Mailinglistenbeitrag vorgeschlagen ) ist die Verwendung der integrierten textcat
Funktion (die hinter dem ||
Operator liegt):
CREATE AGGREGATE textcat_all(
basetype = text,
sfunc = textcat,
stype = text,
initcond = ''
);
Hier ist die CREATE AGGREGATE
Dokumentation.
Dadurch werden einfach alle Saiten ohne Trennzeichen zusammengeklebt. Um ein "," zwischen ihnen einzufügen, ohne es am Ende zu haben, möchten Sie möglicherweise Ihre eigene Verkettungsfunktion erstellen und die oben stehende "Textkatze" ersetzen. Hier ist eine, die ich am 8.3.12 zusammengestellt und getestet habe:
CREATE FUNCTION commacat(acc text, instr text) RETURNS text AS $$
BEGIN
IF acc IS NULL OR acc = '' THEN
RETURN instr;
ELSE
RETURN acc || ', ' || instr;
END IF;
END;
$$ LANGUAGE plpgsql;
Diese Version gibt ein Komma aus, auch wenn der Wert in der Zeile null oder leer ist. Sie erhalten also die folgende Ausgabe:
a, b, c, , e, , g
Wenn Sie zusätzliche Kommas entfernen möchten, um dies auszugeben:
a, b, c, e, g
Fügen ELSIF
Sie dann der Funktion einen Häkchen wie folgt hinzu:
CREATE FUNCTION commacat_ignore_nulls(acc text, instr text) RETURNS text AS $$
BEGIN
IF acc IS NULL OR acc = '' THEN
RETURN instr;
ELSIF instr IS NULL OR instr = '' THEN
RETURN acc;
ELSE
RETURN acc || ', ' || instr;
END IF;
END;
$$ LANGUAGE plpgsql;