418

グループ内のフィールドの文字列をクエリで連結する方法を探しています。たとえば、次のテーブルがあります。

ID   COMPANY_ID   EMPLOYEE
1    1            Anna
2    1            Bill
3    2            Carol
4    2            Dave

そして、次のようなものを取得するために company_id でグループ化したいと思いました:

COMPANY_ID   EMPLOYEE
1            Anna, Bill
2            Carol, Dave

これを行うためにmySQLに組み込み関数がありますgroup_concat

4

14 に答える 14

633

PostgreSQL 9.0 以降:

現代のPostgres(2010年以降)にはstring_agg(expression, delimiter)、質問者が探していたことを正確に行う機能があります。

SELECT company_id, string_agg(employee, ', ')
FROM mytable
GROUP BY company_id;

Postgres 9では、任意の集計式でORDER BY句を指定する機能も追加されました。そうしないと、すべての結果を並べ替えるか、未定義の順序を処理する必要があります。したがって、次のように記述できます。

SELECT company_id, string_agg(employee, ', ' ORDER BY employee)
FROM mytable
GROUP BY company_id;

PostgreSQL 8.4.x:

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;

PostgreSQL 8.3.x 以前:

この質問が最初に提起されたとき、文字列を連結する組み込みの集計関数はありませんでした。最も単純なカスタム実装 (このメーリング リストの投稿で 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;
于 2008-09-04T15:03:25.147 に答える
109

Postgres の組み込み配列関数を使用するのはどうですか? 少なくとも 8.4 では、これはそのまま使用できます。

SELECT company_id, array_to_string(array_agg(employee), ',')
FROM mytable
GROUP BY company_id;
于 2010-02-18T22:55:30.450 に答える
22

PostgreSQL 9.0 以降では、 string_aggという集計関数を使用できます。新しい SQL は次のようになります。

SELECT company_id, string_agg(employee, ', ')
FROM mytable
GROUP BY company_id;

于 2011-05-26T13:44:22.837 に答える
14

いくつかの検索の後に見つけたので、私は答えの信用を主張しません:

私が知らなかったのは、PostgreSQL ではCREATE AGGREGATEを使用して独自の集計関数を定義できるということです。

PostgreSQL リストのこの投稿は、必要なことを行う関数を作成することがいかに簡単かを示しています。

CREATE AGGREGATE textcat_all(
  basetype    = text,
  sfunc       = textcat,
  stype       = text,
  initcond    = ''
);

SELECT company_id, textcat_all(employee || ', ')
FROM mytable
GROUP BY company_id;
于 2008-09-04T14:35:09.177 に答える
7

既に述べたように、独自の集計関数を作成することは正しいことです。これが私の連結集約関数です (フランス語で詳細を見つけることができます):

CREATE OR REPLACE FUNCTION concat2(text, text) RETURNS text AS '
    SELECT CASE WHEN $1 IS NULL OR $1 = \'\' THEN $2
            WHEN $2 IS NULL OR $2 = \'\' THEN $1
            ELSE $1 || \' / \' || $2
            END; 
'
 LANGUAGE SQL;

CREATE AGGREGATE concatenate (
  sfunc = concat2,
  basetype = text,
  stype = text,
  initcond = ''

);

そして、次のように使用します。

SELECT company_id, concatenate(employee) AS employees FROM ...
于 2008-12-09T19:54:44.393 に答える
5

この最新のアナウンスリストスニペットは、8.4にアップグレードする場合に役立つ可能性があります。

8.4が非常に効率的なネイティブ関数でリリースされるまで、PostgreSQLドキュメントにarray_accum()関数を追加して、任意の列を配列にロールアップし、アプリケーションコードで使用したり、array_to_string()と組み合わせてフォーマットしたりできます。リストとして:

http://www.postgresql.org/docs/current/static/xaggr.html

8.4開発ドキュメントにリンクしますが、まだこの機能がリストされていないようです。

于 2009-02-09T13:22:57.103 に答える
5

Postgres docs を使用して、Kev の回答をフォローアップします。

まず、要素の配列を作成してから、組み込みarray_to_string関数を使用します。

CREATE AGGREGATE array_accum (anyelement)
(
 sfunc = array_append,
 stype = anyarray,
 initcond = '{}'
);

select array_to_string(array_accum(name),'|') from table group by id;
于 2009-05-19T12:13:33.370 に答える
5

文字列連結のカスタム集約関数の使用についてもう一度説明します。select ステートメントは行を任意の順序で配置することを覚えておく必要があるため、fromステートメントでorder by句を使用してサブselectを実行する必要があります。次に、文字列を集約するためのgroup by句を使用した外部選択。

SELECT custom_aggregate(MY.special_strings)
FROM (SELECT special_strings, grouping_column 
        FROM a_table 
        ORDER BY ordering_column) MY
GROUP BY MY.grouping_column
于 2009-09-03T16:24:28.743 に答える
3

このPostgreSQLのドキュメントは役に立ちました:http ://www.postgresql.org/docs/8.0/interactive/functions-conditional.html 。

私の場合、フィールドが空でない場合は、フィールドを角かっこで囲んで連結するプレーンSQLを探しました。

select itemid, 
  CASE 
    itemdescription WHEN '' THEN itemname 
    ELSE itemname || ' (' || itemdescription || ')' 
  END 
from items;
于 2009-02-19T04:01:34.507 に答える