您好我正在使用此查询来获取不同的行;分离值
表就像
row_id aggregator
1 12;45
2 25
使用此查询我想要输出
row_id aggregator
1 12
1 45
2 25
我正在使用以下查询
SELECT
DISTINCT ROW_ID,
REGEXP_SUBSTR(AGGREGATOR,'[^;]+',1,LEVEL) as AGGREGATOR,
FROM DUMMY_1
CONNECT BY REGEXP_SUBSTR(AGGREGATOR,'[^;]+',1,LEVEL) IS NOT NULL;
但即使是300条记录也很慢 我必须为40000条记录工作。
答案 0 :(得分:4)
有时流水线表可以更快,试试这个:
create or replace type t is object(word varchar2(100), pk number);
/
create or replace type t_tab as table of t;
/
create or replace function split_string(del in varchar2) return t_tab
pipelined is
word varchar2(4000);
str_t varchar2(4000) ;
v_del_i number;
iid number;
cursor c is
select * from DUMMY_1;
begin
for r in c loop
str_t := r.aggregator;
iid := r.row_id;
while str_t is not null loop
v_del_i := instr(str_t, del, 1, 1);
if v_del_i = 0 then
word := str_t;
str_t := '';
else
word := substr(str_t, 1, v_del_i - 1);
str_t := substr(str_t, v_del_i + 1);
end if;
pipe row(t(word, iid));
end loop;
end loop;
return;
end split_string;
And here is another demo包含22行,每行包含3个vals - 查看第一个和第二个查询之间的差异..
答案 1 :(得分:4)
已知正则表达式是昂贵的函数,因此在性能至关重要时(例如在CONNECT BY
子句中使用标准函数),应尽量减少它们的使用。
使用标准函数(INSTR
,SUBSTR
,REPLACE
)会更有效,但生成的代码将难以阅读/理解/维护。
我无法抗拒写一个递归QTE,我比正则表达式和标准函数更有效率。此外,递归QTE查询可以说是一种优雅。你需要Oracle 11.2:
WITH rec_sql(row_id, aggregator, lvl, tail) AS (
SELECT row_id,
nvl(substr(aggregator, 1, instr(aggregator, ';') - 1),
aggregator),
1 lvl,
CASE WHEN instr(aggregator, ';') > 0 THEN
substr(aggregator, instr(aggregator, ';') + 1)
END tail
FROM dummy_1 initialization
UNION ALL
SELECT r.row_id,
nvl(substr(tail, 1, instr(tail, ';') - 1), tail),
lvl + 1,
CASE WHEN instr(tail, ';') > 0 THEN
substr(tail, instr(tail, ';') + 1)
END tail
FROM rec_sql r
WHERE r.tail IS NOT NULL
)
SELECT * FROM rec_sql;
您可以在SQLFiddle上看到此解决方案非常高效且与@A.B.Cade's solution相同。 (感谢A.B.Cade的测试用例)。
答案 2 :(得分:0)
您的connect by
产生的记录比需要的多得多,这就是性能低下的原因,您需要使用distinct
来限制记录数。确实需要distinct
的方法是:
select row_id, regexp_substr(aggregator,'[^;]+',1,n) aggregator
from dummy_1, (select level n from dual connect by level < 100)
where n <= regexp_count(aggregator,';')+1
答案 3 :(得分:-1)
我认为DISTINCT可能存在问题。此外,我不明白为什么你需要CONNECT BY REGEXP_SUBSTR(AGGREGATOR,'[^;] +',1,LEVEL)IS NOT NULL。您在选择和连接中使用正则表达式。你可以使用AGGREGATOR IS NOT而不是connect by?找到一种方法来摆脱不同并修改您的查询。您可以使用EXISTS代替不同的...为了帮助您,我需要表格和数据。
SELECT * FROM
(
SELECT REGEXP_SUBSTR(AGGREGATOR ,'[^;]+',1,LEVEL) as AGGREGATOR
FROM your_table
)
WHERE AGGREGATOR IS NOT NULL
/