我有一张桌子:Table_1如下所示:
id | column1
-----------------
10 | abc, kdm
20 | xyz, lop, nkk
我想要的是转换表如下所示:
id | column1
-----------------
10 | abc
10 | kdm
20 | xyz
20 | lop
20 | nkk
为此,我使用了这样的查询:
select id, regexp_substr(column1,'[^,]+', 1, level) from Table_1
connect by regexp_substr(column1, '[^,]+', 1, level) is not null;
只要逗号分隔值的数量较少,此查询就可以正常工作。但是当它增长时,它会消耗越来越多的时间来处理。
我想到的一个解决方案是创建一个单独的表,然后通过迭代Table_1的值来插入值。
伪代码如下:
FOR r in each row
FOR i in 1..length(comma_separated_values)
insert into new_table values(id, select regexp_substr(column1,'[^,]+', 1, i) from Table_1
End LOOP;
End LOOP;
但是,由于逗号分隔值增长也会消耗很多时间,是否还有其他最佳方法(首选不使用其他表,但临时/虚拟表可以)?
我正在使用Oracle SQL。
提前致谢。
答案 0 :(得分:1)
显然兰迪建议修复根本问题是理想的。如果不可能,那么可以使用各种选项。列出了许多here
。通常,虽然可以提高性能的简单解决方案是在column1中找到最大数量的值,创建包含许多列的临时表,然后将该临时表转换为所需的格式。即,有一个中间步骤,表格看起来像id|val1|val2|val3|..|valn
答案 1 :(得分:1)
规范化问题无法承受,您的原始查询实际上不起作用。在测试数据上运行时:
SQL> with Table_1(id, column1) as (
2 select 10, 'abc, kdm' from dual
3 union
4 select 20, 'xyz, lop, nkk' from dual
5 )
6 select id, regexp_substr(column1,'[^,]+', 1, level) from Table_1
7 connect by regexp_substr(column1, '[^,]+', 1, level) is not null;
ID REGEXP_SUBSTR
---------- -------------
10 abc
10 kdm
20 nkk
20 lop
20 nkk
20 xyz
10 kdm
20 nkk
20 lop
20 nkk
10 rows selected.
SQL>
因此,当您添加更多值时,问题会呈指数级增长,从而降低性能。通过添加第三行进行测试。此外,您的分隔符是逗号空格,而不仅仅是逗号。 And the regex form used to parse the list ('[^,]+')
does not work with nulls and should be avoided。不幸的是,它是最常见的正则表达式,你会看到它作为解析列表的答案。
试试这个,它应该轻松处理更大的列表:
SQL> with Table_1(id, column1) as (
select 10, 'abc, kdm' from dual
union
select 20, 'xyz, lop, nkk' from dual
)
SELECT id, -- column1,
-- COLUMN_VALUE AS match_nbr,
REGEXP_SUBSTR( column1 ,'(.*?)(, |$)', 1, COLUMN_VALUE, NULL, 1 ) AS match_value
FROM
Table_1,
TABLE(
CAST(
MULTISET(
SELECT LEVEL
FROM DUAL
CONNECT BY LEVEL <= REGEXP_COUNT(column1 , ',' )+1
) AS SYS.ODCINUMBERLIST
)
);
ID MATCH_VALUE
---------- -------------
10 abc
10 kdm
20 xyz
20 lop
20 nkk
SQL>
基本上,这会创建一个表,每行一行,列表中的元素数(包含元素编号)并将其与主表连接。
取消注释COLUMN_VALUE值行以查看元素的编号。
它假定数据不包含逗号。
答案 2 :(得分:0)
您可以尝试使用DBMS_UTILITY.COMMA_TO_TABLE程序,我猜它应该比用户定义的解决方案更快。
文档链接:http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_util.htm