使用 regex_substr 从 oracle 中的另一列获取相应的值
using regex_substr to get corresponding value from another column in oracle
我有以下有效的查询,它给出了与我在 where 子句中作为名称给出的键对应的第 n 个字符串(分隔符为 ##)
select names from (
select
regexp_substr('a##b##c##d##e##f','[^##]+', 1, level) as names,
rownum as nth
from dual
connect by regexp_substr('a##b##c##d##e##f', '[^##]+', 1, level) is not null
)
where nth in (
select nth from (
select
regexp_substr('150##200##13##8##51##61','[^##]+', 1, level) as names,
rownum as nth
from dual
connect by regexp_substr('150##200##13##8##51##61', '[^##]+', 1, level) is not null
)
where names = '200'
)
现在,我有一个 table 临时表,其中包含 3 列 x、y 和 z,其中 x 具有类似 a##b##c##d##e##f 的字符串,y 具有 1##2## 3##4##5##6 和 z 会有像 1 这样的数字。
如果我有这样的行
- a##b##c##d##e##f 150##200##13##8##51##61 200
- a##b##c##d##e##f 1##2##3##4##5##6 2
- g##h##i##j##k##l 1##2##3##4##5##99 99
我想要这样的输出
- a##b##c##d##e##f 150##200##13##8##51##61 200 b
- a##b##c##d##e##f 1##2##3##4##5##6 2 b
- g##h##i##j##k##l 1##2##3##4##5##99 99 l
在上述查询中简单地插入 "temp" 代替 dual 需要很长时间,因为数据库有超过 50k 行。任何更好的解决方案或如何解决这个问题?
您可能会找到一个简单的 SQL 解决方案,但我更愿意将关键的子字符串功能封装在一个函数中。之后查询很简单
更新
with tcols as (
select rownum colnum from dual connect by level <= 6 /* (max) number of columns */),
t2 as (
select x,y,z, colnum,
nth_substring(y,'#',colnum) subs
from regexp_tst, tcols
)
select
x,y,z, colnum,
nth_substring(x,'#',colnum) a
from t2
where subs = z
;
.
X Y Z A
---------------- ---------------- ---------- ----
a##b##c##d##e##f 1##2##3##4##5##6 1 a
a##b##c##d##e##f 1##2##3##4##5##6 2 b
g##h##i##j##k##l 1##2##3##4##5##6 3 i
所需功能如下(您可能需要调整裁剪和重复分隔符逻辑)
create or replace function nth_substring( i_str VARCHAR2, i_del VARCHAR2, i_pos NUMBER)
/*
find n-th substring in delimited string
i_str input string e.g. a##b##c##d##e##f
i_del delimiter character
i_pos position of the strin starting from 1
*/
return VARCHAR2 is
BEGIN
return rtrim(ltrim(regexp_substr(i_str,'[^'||i_del||']+', 1, i_pos)));
END;
/
我有以下有效的查询,它给出了与我在 where 子句中作为名称给出的键对应的第 n 个字符串(分隔符为 ##)
select names from (
select
regexp_substr('a##b##c##d##e##f','[^##]+', 1, level) as names,
rownum as nth
from dual
connect by regexp_substr('a##b##c##d##e##f', '[^##]+', 1, level) is not null
)
where nth in (
select nth from (
select
regexp_substr('150##200##13##8##51##61','[^##]+', 1, level) as names,
rownum as nth
from dual
connect by regexp_substr('150##200##13##8##51##61', '[^##]+', 1, level) is not null
)
where names = '200'
)
现在,我有一个 table 临时表,其中包含 3 列 x、y 和 z,其中 x 具有类似 a##b##c##d##e##f 的字符串,y 具有 1##2## 3##4##5##6 和 z 会有像 1 这样的数字。
如果我有这样的行
- a##b##c##d##e##f 150##200##13##8##51##61 200
- a##b##c##d##e##f 1##2##3##4##5##6 2
- g##h##i##j##k##l 1##2##3##4##5##99 99
我想要这样的输出
- a##b##c##d##e##f 150##200##13##8##51##61 200 b
- a##b##c##d##e##f 1##2##3##4##5##6 2 b
- g##h##i##j##k##l 1##2##3##4##5##99 99 l
在上述查询中简单地插入 "temp" 代替 dual 需要很长时间,因为数据库有超过 50k 行。任何更好的解决方案或如何解决这个问题?
您可能会找到一个简单的 SQL 解决方案,但我更愿意将关键的子字符串功能封装在一个函数中。之后查询很简单
更新
with tcols as (
select rownum colnum from dual connect by level <= 6 /* (max) number of columns */),
t2 as (
select x,y,z, colnum,
nth_substring(y,'#',colnum) subs
from regexp_tst, tcols
)
select
x,y,z, colnum,
nth_substring(x,'#',colnum) a
from t2
where subs = z
;
.
X Y Z A
---------------- ---------------- ---------- ----
a##b##c##d##e##f 1##2##3##4##5##6 1 a
a##b##c##d##e##f 1##2##3##4##5##6 2 b
g##h##i##j##k##l 1##2##3##4##5##6 3 i
所需功能如下(您可能需要调整裁剪和重复分隔符逻辑)
create or replace function nth_substring( i_str VARCHAR2, i_del VARCHAR2, i_pos NUMBER)
/*
find n-th substring in delimited string
i_str input string e.g. a##b##c##d##e##f
i_del delimiter character
i_pos position of the strin starting from 1
*/
return VARCHAR2 is
BEGIN
return rtrim(ltrim(regexp_substr(i_str,'[^'||i_del||']+', 1, i_pos)));
END;
/