199

複数の行からの列値を連結するSQLを構築することは可能でしょうか?

次に例を示します。

表A

PID
A
B
C

表B

PID配列説明

A1持っている
A2いいね
3日。
B1お疲れ様でした。
C1はい
C2できる
C 3 do
C 4この作品!

SQLの出力は次のようになります-

PID説明
A良い一日を。
Bお疲れ様でした。
Cはい、私たちはこの仕事をすることができます!

つまり、基本的に、出力テーブルのDesc列は、テーブルBのSEQ値を連結したものですか?

SQLに関するヘルプはありますか?

4

10 に答える 10

278

使用しているバージョンに応じて、いくつかの方法があります。文字列集約手法に関するOracleのドキュメントを参照してください。非常に一般的なものは、以下を使用することLISTAGGです。

SELECT pid, LISTAGG(Desc, ' ') WITHIN GROUP (ORDER BY seq) AS description
FROM B GROUP BY pid;

次に、に参加しAて、必要なものを選びpidsます。

注:箱から出して、列でLISTAGGのみ正しく機能しVARCHAR2ます。

于 2011-01-13T23:42:31.993 に答える
20

XMLAGG11.2より前のバージョンで動作する関数もあります。WM_CONCAT文書化されておらず、Oracleによってサポートされていないため、本番システムでは使用しないことをお勧めします。

あなたと一緒XMLAGGに次のことができます:

SELECT XMLAGG(XMLELEMENT(E,ename||',')).EXTRACT('//text()') "Result" 
FROM employee_names

これは何ですか

  • enameテーブルの列(コンマで連結)の値をemployee_namesxml要素(タグE)に入れます
  • このテキストを抽出します
  • xmlを集約します(連結します)
  • 結果の列を「結果」と呼びます
于 2013-05-31T09:11:25.790 に答える
14

SQLモデル句を使用する場合:

SQL> select pid
  2       , ltrim(sentence) sentence
  3    from ( select pid
  4                , seq
  5                , sentence
  6             from b
  7            model
  8                  partition by (pid)
  9                  dimension by (seq)
 10                  measures (descr,cast(null as varchar2(100)) as sentence)
 11                  ( sentence[any] order by seq desc
 12                    = descr[cv()] || ' ' || sentence[cv()+1]
 13                  )
 14         )
 15   where seq = 1
 16  /

P SENTENCE
- ---------------------------------------------------------------------------
A Have a nice day
B Nice Work.
C Yes we can do this work!

3 rows selected.

私はこれについてここに書きました。また、OTNスレッドへのリンクをたどると、パフォーマンスの比較など、さらにいくつかの情報が見つかります。

于 2011-01-14T09:20:47.790 に答える
11

LISTAGG分析関数はOracle11gリリース2で導入され、文字を非常に簡単に集約できるようになりました。11gリリース2を使用している場合は、この関数を文字列の集約に使用する必要があります。文字列の連結の詳細については、以下のURLを参照してください。

http://www.oracle-base.com/articles/misc/StringAggregationTechniques.php

文字列の連結

于 2012-03-01T14:03:12.607 に答える
8

ほとんどの答えが示唆しているように、LISTAGGそれは明白な選択肢です。ただし、厄介な点の1つLISTAGGは、連結された文字列の全長が4000文字(VARCHAR2SQLでの制限)を超えると、以下のエラーがスローされることです。これは、12.1までのOracleバージョンでは管理が困難です。

ORA-01489:文字列連結の結果が長すぎます

12cR2で追加された新機能は、のON OVERFLOW句ですLISTAGG。この句を含むクエリは次のようになります。

SELECT pid, LISTAGG(Desc, ' ' on overflow truncate) WITHIN GROUP (ORDER BY seq) AS desc
FROM B GROUP BY pid;

上記は出力を4000文字に制限しますが、 ORA-01489エラーはスローされません。

これらは、ON OVERFLOW句の追加オプションの一部です。

  • ON OVERFLOW TRUNCATE 'Contd..' :これは'Contd..'文字列の最後に表示されます(デフォルトは...
  • ON OVERFLOW TRUNCATE '' :これにより、終了文字列なしで4000文字が表示されます。
  • ON OVERFLOW TRUNCATE WITH COUNT:終了文字後の最後の合計文字数を表示します。例:-' ...(5512)'
  • ON OVERFLOW ERRORLISTAGG:エラーで失敗する ことが予想される場合ORA-01489(とにかくデフォルトです)。
于 2018-02-05T12:26:28.180 に答える
7

Oracle 9i(またはそれ以前)を使用してこの問題を解決する必要がある場合は、LISTAGGが使用できないため、おそらくSYS_CONNECT_BY_PATHを使用する必要があります。

OPに回答するために、次のクエリはテーブルAのPIDを表示し、テーブルBのすべてのDESC列を連結します。

SELECT pid, SUBSTR (MAX (SYS_CONNECT_BY_PATH (description, ', ')), 3) all_descriptions
FROM (
       SELECT ROW_NUMBER () OVER (PARTITION BY pid ORDER BY pid, seq) rnum, pid, description
       FROM (
              SELECT a.pid, seq, description
              FROM table_a a, table_b b
              WHERE a.pid = b.pid(+)
             )
      )
START WITH rnum = 1
CONNECT BY PRIOR rnum = rnum - 1 AND PRIOR pid = pid
GROUP BY pid
ORDER BY pid;

キーと値がすべて1つのテーブルに含まれている場合もあります。次のクエリは、テーブルAがなく、テーブルBのみが存在する場合に使用できます。

SELECT pid, SUBSTR (MAX (SYS_CONNECT_BY_PATH (description, ', ')), 3) all_descriptions
FROM (
       SELECT ROW_NUMBER () OVER (PARTITION BY pid ORDER BY pid, seq) rnum, pid, description
       FROM (
              SELECT pid, seq, description
              FROM table_b
             )
      )
START WITH rnum = 1
CONNECT BY PRIOR rnum = rnum - 1 AND PRIOR pid = pid
GROUP BY pid
ORDER BY pid;

すべての値は、必要に応じて並べ替えることができます。個々の連結された説明は、PARTITION BY句で並べ替えることができ、PIDのリストは、最後のORDERBY句で並べ替えることができます。


または、テーブル全体のすべての値を1つの行に連結したい場合があります。

ここでの重要なアイデアは、連結される記述のグループに人為的な値を使用することです。

次のクエリでは、定数文字列「1」が使用されていますが、任意の値が機能します。

SELECT SUBSTR (MAX (SYS_CONNECT_BY_PATH (description, ', ')), 3) all_descriptions
FROM (
       SELECT ROW_NUMBER () OVER (PARTITION BY unique_id ORDER BY pid, seq) rnum, description
       FROM (
              SELECT '1' unique_id, b.pid, b.seq, b.description
              FROM table_b b
             )
      )
START WITH rnum = 1
CONNECT BY PRIOR rnum = rnum - 1;

個々の連結された説明は、PARTITIONBY句で並べ替えることができます。

このページの他のいくつかの回答でも、この非常に役立つリファレンスについて言及しています: https ://oracle-base.com/articles/misc/string-aggregation-techniques

于 2017-02-01T17:27:42.380 に答える
5
  1. 並べ替えが必須の場合、LISTAGGは最高のパフォーマンスを提供します(00:00:05.85)

    SELECT pid, LISTAGG(Desc, ' ') WITHIN GROUP (ORDER BY seq) AS description FROM B GROUP BY pid;

  2. COLLECTは、並べ替えが不要な場合に最高のパフォーマンスを提供します(00:00:02.90):

    SELECT pid, TO_STRING(CAST(COLLECT(Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid;

  3. 注文を伴うCOLLECTは少し遅い(00:00:07.08):

    SELECT pid, TO_STRING(CAST(COLLECT(Desc ORDER BY Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid;

他のすべてのテクニックは遅かった。

于 2015-02-12T16:59:54.017 に答える
1

selectクエリを実行する前に、次のコマンドを実行します。

SET SERVEROUT ON SIZE 6000

SELECT XMLAGG(XMLELEMENT(E,SUPLR_SUPLR_ID||',')).EXTRACT('//text()') "SUPPLIER" 
FROM SUPPLIERS;
于 2013-10-10T06:46:12.150 に答える
-1

このコードを試してください:

 SELECT XMLAGG(XMLELEMENT(E,fieldname||',')).EXTRACT('//text()') "FieldNames"
    FROM FIELD_MASTER
    WHERE FIELD_ID > 10 AND FIELD_AREA != 'NEBRASKA';
于 2014-11-19T11:16:26.110 に答える
-3

連結する場所を選択して、SQL関数を呼び出します。

例えば:

select PID, dbo.MyConcat(PID)
   from TableA;

次に、SQL関数の場合:

Function MyConcat(@PID varchar(10))
returns varchar(1000)
as
begin

declare @x varchar(1000);

select @x = isnull(@x +',', @x, @x +',') + Desc
  from TableB
    where PID = @PID;

return @x;

end

関数ヘッダーの構文が間違っている可能性がありますが、原則は機能します。

于 2015-10-21T19:06:19.420 に答える