Bin heute über eine schlechte Implementierung von folgender Aufgabe gestoßen:
Gebe eine komma-separierte Liste (comma separate value) innerhalb der Gruppierung aus.
Bevor wir zur Lösung kommen, sollten wir uns noch ein Set von Daten zum Testen vorbereiten. Danach werden wir uns verschiedene Lösungen anschauen, die in den unterschiedlichsten PostgreSQL Versionen funktionieren.
Vorbereitung
-- Schema als Spielwiese anlegen CREATE SCHEMA play; -- Tabelle mit den Testdaten erstellen CREATE TABLE play.str_agg(value INT, value_group INT); INSERT INTO play.str_agg VALUES (1,1); INSERT INTO play.str_agg VALUES (3,1); INSERT INTO play.str_agg VALUES (5,1); INSERT INTO play.str_agg VALUES (4,1); INSERT INTO play.str_agg VALUES (2,1);
Vor PostgreSQL 8.4
Vor der 8.4 (und natürlich auch die nachfolgenden Versionen) benötigen wir für die Erledigung der Aufgabe ein besonderes PostgreSQL-Objekt. Wenn wir von Gruppierungen sprechen, liegt es nahe die Lösung mit Aggregaten anzugehen.
CREATE AGGREGATE play.to_csv( basetype = TEXT, sfunc = textcat, stype = TEXT, initcond = '' ); SELECT value_group, play.to_csv(value::TEXT || ',') AS _csv FROM play.str_agg GROUP BY value_group;
Ab PostgreSQL 8.4
Mit der Version 8.4 kamen einige array-Funktionen (array_agg, array_to_string) mit, die wir jetzt benötigen und somit auf das Aggregat verzichten können.
SELECT value_group, array_to_string( array_agg(value), ',') AS _csv FROM play.str_agg GROUP BY value_group;
Ab PostgreSQL 9.0
Mit der Version 9.0 existiert für die Aufgabe nun eine spezielle Funktion – string_agg.
SELECT value_group, string_agg(value::text, ',') AS _csv FROM play.str_agg GROUP BY value_group;