0

我有一个包含两列的表,如下所示:

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

该表有两列,第二列包含单个值或多个值,作为用分号分隔的字符串。

我想要做的是对于值是具有多个值的字符串的每一行,我想拆分字符串并使用每个值插入一个新行(从第一列复制新行的值) .

使用上面的示例数据,输出将是这样的:

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

2
select id, txt from table1
model partition by (id) dimension by (1 as n) measures (txt) (
  txt[for n from regexp_count(txt[1], '[^;]+') to 1 decrement 1] = 
  regexp_substr(txt[1], '[^;]+', 1, cv(n))
)
order by id, n

小提琴

于 2013-09-04T17:52:00.750 回答
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

这是一个解决方案,我从另一个网站获取了一些代码,但不记得是谁然后修改了它。我在临时表中添加了一些数据以显示它有效

DECLARE @DATA TABLE (COL1 NVARCHAR(10), COL2 NVARCHAR(100))
DECLARE @RESULT TABLE (COL1 NVARCHAR(10),COL2 NVARCHAR(100))
DECLARE @COL1 NVARCHAR(10)
DECLARE @COL2 NVARCHAR(10)

INSERT INTO @DATA VALUES ( 'A001',    'A1;A2;A3')
INSERT INTO @DATA VALUES ( 'B002',    'B1')
INSERT INTO @DATA VALUES ( 'C003',    'C1;C2')
INSERT INTO @DATA VALUES ( 'D004',    'D1;D2;D3;D4')
INSERT INTO @DATA VALUES ( 'E005',    'E1')


DECLARE CURDB CURSOR FOR
SELECT  *
FROM    @DATA

OPEN CURDB

FETCH NEXT FROM CURDB
INTO @COL1, @COL2

WHILE @@FETCH_STATUS = 0
BEGIN

DECLARE @S varchar(max),
@Split char(1),
@X xml

SELECT @S = @COL2,
@Split = ';'

SELECT @X = CONVERT(xml,'<root><s>' + REPLACE(@S,@Split,'</s><s>') + '</s></root>')

INSERT INTO @RESULT
SELECT @COL1,[Value] = T.c.value('.','varchar(20)')
FROM @X.nodes('/root/s') T(c)

FETCH NEXT FROM CURDB
INTO @COL1, @COL2

END 
CLOSE CURDB;
DEALLOCATE CURDB;

SELECT *
FROM @RESULT
于 2013-09-04T15:34:00.940 回答
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

可以使用以下查询来转换行中的逗号分隔值

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 回答