0

以下に示すように、2つの列を持つテーブルがあります。

A001    A1;A2;A3
B002    B1
C003    C1;C2
D004    D1;D2;D3;D4
E005    E1

テーブルには 2 つの列があり、2 番目の列にはセミコロンで区切られた文字列として単一の値または複数の値が含まれています。

私がやりたいことは、値が複数の値を持つ文字列である行ごとに、文字列を分割し、各値を使用して新しい行を挿入したい (新しい行の最初の列から値を複製する) .

上記のサンプル データを使用すると、出力は次のようになります。

A001 A1
A001 A2
A001 A3
B002 B1
C003 C1
C003 C2
D004 D1
D004 D2
D004 D3
D004 D4
E005 E1
4

5 に答える 5

1

行から列にデータを転置する方法は多数あります。

この場合、文字列をさまざまな要素に分割する必要もあるため、パイプライン関数を使用するのが好きです。

SQL> CREATE OR REPLACE PACKAGE pkg AS
  2     TYPE tab_varchar2 IS TABLE OF VARCHAR2(4000);
  3     FUNCTION split_string (p VARCHAR2) RETURN tab_varchar2 PIPELINED;
  4  END;
  5  /

Package created

SQL> CREATE OR REPLACE PACKAGE BODY pkg AS
  2     FUNCTION split_string (p VARCHAR2) RETURN tab_varchar2 PIPELINED IS
  3        l_tail    LONG := p;
  4        l_separator NUMBER;
  5     BEGIN
  6        WHILE l_tail IS NOT NULL LOOP
  7           l_separator := instr(l_tail, ';');
  8           IF l_separator <= 0 THEN
  9              PIPE ROW (l_tail);
 10              l_tail := '';
 11           ELSE
 12              PIPE ROW (substr(l_tail, 1, l_separator - 1));
 13              l_tail := substr(l_tail, l_separator + 1);
 14           END IF;
 15        END LOOP;
 16        RETURN;
 17     END split_string;
 18  END;
 19  /

Package body created

ラテラル結合を使用してデータをクエリします。

SQL> WITH data AS (
  2     SELECT 'A001' ID, 'A1;A2;A3' txt FROM dual UNION ALL
  3     SELECT 'B002' ID, 'B1' txt FROM dual UNION ALL
  4     SELECT 'C003' ID, 'C1;C2' txt FROM dual UNION ALL
  5     SELECT 'D004' ID, 'D1;D2;D3;D4' txt FROM dual UNION ALL
  6     SELECT 'E005' ID, 'E1' txt FROM dual
  7  )
  8  SELECT d.id, COLUMN_VALUE
  9    FROM data d
 10         CROSS JOIN TABLE(pkg.split_string(d.txt));

ID           COLUMN_VALUE
------------ --------------------------------------------------
A001         A1
A001         A2
A001         A3
B002         B1
C003         C1
C003         C2
D004         D1
D004         D2
D004         D3
D004         D4
E005         E1
于 2013-09-04T15:36:10.433 に答える
1
with src as
(
        select 'A001' col1, 'A1;A2;A3' col2 from dual union all
        select 'B002',      'B1'            from dual union all
        select 'C003',      'C1;C2'         from dual union all
        select 'D004',      'D1;D2;D3;D4'   from dual union all
        select 'E005',      'E1'            from dual
)
, explode as
(
        select  col1
        ,       regexp_substr(col2, '\w+', 1, 1) as col2_1
        ,       regexp_substr(col2, '\w+', 1, 2) as col2_2
        ,       regexp_substr(col2, '\w+', 1, 3) as col2_3
        ,       regexp_substr(col2, '\w+', 1, 4) as col2_4
        --      if there is more add more...
        from    src
)
select col1, col2_1 from explode where col2_1 is not null union all
select col1, col2_2 from explode where col2_2 is not null union all
select col1, col2_3 from explode where col2_3 is not null union all
select col1, col2_4 from explode where col2_4 is not null 
order by col1
;

結果:

/*
A001    A1
A001    A2
A001    A3
B002    B1
C003    C2
C003    C1
D004    D1
D004    D4
D004    D2
D004    D3
E005    E1
*/
于 2013-09-04T15:35:14.733 に答える
1

以下のクエリを使用して、カンマ区切りの値を行に変換できます

SELECT trim(x.column_value.extract('e/text()')) COLUMNS
from t t, table (xmlsequence(xmltype('<e><e>' || replace(valuestring,':','</e><e>')||  
'</e></e>').extract('e/e'))) x   );  
于 2013-09-04T17:06:15.370 に答える