web-dev-qa-db-ja.com

複数の行を1つの行に集約するOracle SQLクエリはありますか?

次のような表があります。

A 1 
A 2 
B 1 
B 2

そして、私はこのような結果セットを生成したいです:

A 1 2 
B 1 2

これを行うSQLステートメントはありますか? Oracleを使用しています。

関連する質問:

31
user128807

使用しているOracleのバージョンによって異なります。 wm_concat()関数をサポートしている場合は、次のように簡単に実行できます。

SELECT field1, wm_concat(field2) FROM YourTable GROUP BY field2;

wm_concat()は基本的に、MySQLの group_concat() と同じように機能します。文書化されていない可能性があるため、古いsqlplusを起動して、存在するかどうかを確認します。

そこがそこにない場合、自分で同等のものを実装する必要があります。 Oracle-base.comの 文字列集約ページ でこれを行う方法に関するいくつかの指示を見つけることができます。

28
John Hyland

かなり古いトピックですが、Oracleがその間に改善したため、他の人を助けることができました。

[〜#〜] listagg [〜#〜] 関数はあなたが探しているものです(少なくとも11gで)

21
user1973071

Oracle 10g+

SELECT  *
FROM    (
        SELECT  *
        FROM    mytable
        MODEL
        PARTITION BY
                (grouper)
        DIMENSION BY
                (ROW_NUMBER() OVER (PARTITION BY grouper ORDER BY id) AS rn)
        MEASURES
                (val, val AS group_concat, 0 AS mark)
        RULES SEQUENTIAL ORDER (
                group_concat[rn > 1] ORDER BY rn = group_concat[CV() - 1] || ', ' || val[CV()],
                mark[ANY] ORDER BY rn = PRESENTV(mark[CV() + 1], 0, 1)
                )
        )
WHERE   mark = 1
ORDER BY
        grouper

説明については、私のブログのこの記事を参照してください。

9
Quassnoi

次のようなものを試してください:

SELECT
    field1,
    RTRIM(REPLACE(REPLACE(XMLAgg(XMLElement("x", field2) ORDER BY field2), '<x>'), '</x>', ' ')) AS field2s
  FROM yourTable
  GROUP BY field1

回答に自由に触発されました このOracleフォーラムにあります

EDIT:このソリューションは証明しましたvery10のようなものが関係するリクエストで集中的なリソース5 行。 Johnが提案 のように、これをカスタム集計関数に置き換えました。

5
Mac

10gを持っている場合、以下の機能を実行する必要があります。

CREATE OR REPLACE FUNCTION get_separated_value (input_val  in  number)
  RETURN VARCHAR2
IS
  return_text  VARCHAR2(10000) := NULL;
BEGIN
  FOR x IN (SELECT col2 FROM table_name WHERE col1 = input_val) LOOP
    return_text := return_text || ' ' || x.col2 ;
  END LOOP;
  RETURN return_text;
END;
/

だから、あなたは次のようにすることができます:

select col1, get_separated_value(col1) from table_name

ここで中段

Oracle 11gを使用している場合、 listagg を使用できます。

SELECT 
    age,
    LISTAGG(name, ' ') WITHIN GROUP (ORDER BY name) "names"
FROM table_x
GROUP BY age

Listaggの場合はここで調整

4
hsuk

ユーザー定義の集計関数: http://www.adp-gmbh.ch/ora/sql/user_def_agg.html

コピーして貼り付けて使用するだけです。 9iで動作します。

2
jva
SELECT a , COLLECT(b) FROM foo GROUP BY a

pl/sqlで使用すると非常に便利です-ユーザー定義のコレクションにキャストできます。

2
haki