PostgreSQL 9.0以降:
Postgresの最近のバージョン(2010年後半以降)にはstring_agg(expression, delimiter)
、デリミタ文字列を指定することさえできるように、質問が要求したとおりに機能する機能があります。
SELECT company_id, string_agg(employee, ', ')
FROM mytable
GROUP BY company_id;
Postgres 9.0は、任意の集計式でORDER BY
句を指定する機能も追加しました。それ以外の場合、順序は未定義です。だから今書くことができます:
SELECT company_id, string_agg(employee, ', ' ORDER BY employee)
FROM mytable
GROUP BY company_id;
または確かに:
SELECT string_agg(actor_name, ', ' ORDER BY first_appearance)
PostgreSQL 8.4以降:
PostgreSQL 8.4(2009年)では、値を配列に連結する集約関数array_agg(expression)
が導入されました。次にarray_to_string()
、目的の結果を与えるために使用できます。
SELECT company_id, array_to_string(array_agg(employee), ', ')
FROM mytable
GROUP BY company_id;
string_agg
8.4より前のバージョンの場合:
9.0より前のデータベースの互換性シムを探している人に遭遇した場合、この句string_agg
以外のすべてを実装することが可能ORDER BY
です。
したがって、以下の定義では、これは9.x Postgres DBと同じように機能するはずです。
SELECT string_agg(name, '; ') AS semi_colon_separated_names FROM things;
しかし、これは構文エラーになります:
SELECT string_agg(name, '; ' ORDER BY name) AS semi_colon_separated_names FROM things;
--> ERROR: syntax error at or near "ORDER"
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
);
カスタムバリエーション(すべてのPostgresバージョン)
9.0より前のバージョンでは、文字列を連結するための組み込み集計関数はありませんでした。最も単純なカスタム実装(このメーリングリストの投稿でVajda Gaboが提案したものなど)は、組み込みtextcat
関数(||
演算子の背後にある)を使用することです。
CREATE AGGREGATE textcat_all(
basetype = text,
sfunc = textcat,
stype = text,
initcond = ''
);
ここにCREATE AGGREGATE
ドキュメントがあります。
これは、セパレータなしですべての文字列を単に接着します。"、"を最後に挿入せずにそれらの間に挿入するには、独自の連結関数を作成し、上記の "textcat"の代わりに使用することができます。ここに私がまとめて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;
このバージョンでは、行の値がnullまたは空であってもコンマが出力されるため、次のような出力が得られます。
a, b, c, , e, , g
これを出力するために余分なコンマを削除したい場合:
a, b, c, e, g
次に、次のELSIF
ように関数にチェックを追加します。
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;