PostgreSQL 9.0 lub nowszy:
Najnowsze wersje Postgres (od końca 2010 r.) Mają string_agg(expression, delimiter)
funkcję, która wykona dokładnie to, o co pytano, nawet umożliwiając określenie ciągu ogranicznika:
SELECT company_id, string_agg(employee, ', ')
FROM mytable
GROUP BY company_id;
Postgres 9.0 dodał także możliwość określenia ORDER BY
klauzuli w dowolnym wyrażeniu zbiorczym ; w przeciwnym razie kolejność jest niezdefiniowana. Możesz teraz pisać:
SELECT company_id, string_agg(employee, ', ' ORDER BY employee)
FROM mytable
GROUP BY company_id;
Lub rzeczywiście:
SELECT string_agg(actor_name, ', ' ORDER BY first_appearance)
PostgreSQL 8.4 lub nowszy:
PostgreSQL 8.4 (w 2009 r.) Wprowadził funkcję agregującą,array_agg(expression)
która łączy wartości w tablicę. Następnie array_to_string()
można go użyć do uzyskania pożądanego rezultatu:
SELECT company_id, array_to_string(array_agg(employee), ', ')
FROM mytable
GROUP BY company_id;
string_agg
dla wersji wcześniejszych niż 8.4:
W przypadku, gdy ktoś natknie się na to, szukając kompatybilnego podkładki dla baz danych starszych niż 9.0, możliwe jest zaimplementowanie wszystkiego string_agg
oprócz ORDER BY
klauzuli.
Tak więc w poniższej definicji powinno to działać tak samo, jak w DB Postgres 9.x:
SELECT string_agg(name, '; ') AS semi_colon_separated_names FROM things;
Będzie to jednak błąd składniowy:
SELECT string_agg(name, '; ' ORDER BY name) AS semi_colon_separated_names FROM things;
--> ERROR: syntax error at or near "ORDER"
Testowany na 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
);
Odmiany niestandardowe (wszystkie wersje Postgres)
Przed wersją 9.0 nie było wbudowanej funkcji agregującej do łączenia łańcuchów. Najprostszą niestandardową implementacją ( zasugerowaną przez Vajdę Gabo w tym poście na liście adresowej ) jest użycie wbudowanej textcat
funkcji (która stoi za ||
operatorem):
CREATE AGGREGATE textcat_all(
basetype = text,
sfunc = textcat,
stype = text,
initcond = ''
);
Oto CREATE AGGREGATE
dokumentacja.
To po prostu skleja wszystkie struny razem, bez separatora. Aby wstawić między nimi znak „,” bez konieczności umieszczania go na końcu, możesz utworzyć własną funkcję konkatenacji i zastąpić ją „textcat” powyżej. Oto jeden zestawiłem i testowałem na 8.3.12:
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;
Ta wersja wyświetli przecinek, nawet jeśli wartość w wierszu jest pusta lub pusta, więc otrzymujesz dane wyjściowe w następujący sposób:
a, b, c, , e, , g
Jeśli wolisz usunąć dodatkowe przecinki, aby to wyświetlić:
a, b, c, e, g
Następnie dodaj ELSIF
zaznaczenie do funkcji w następujący sposób:
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;