我有一个oracle VIEW,该视图在两列中包含一些值,我想将这些值分组到一个新列中,以添加简要说明:
myView :
---------------------------------
ID | col 1 | col 2 |
---------------------------------
1 | 1,2,3,4 |V1,V2,V3,V4
2 | 4,5,6,7 |V5,V6,V7,V8
我想创建一个新视图,添加一个新的第3列:
------------------------------------------------------
ID | col 1 | col 2 |col 3
------------------------------------------------------
1 | 1,2,3,4 |V1,V2,V3,V4 |1,V1 2,V2 3,V3 4,V4
2 | 5,6,7,8 |V5,V6,V7,V8 |5,V5 6,V6 7,V7 8,V8
预先感谢您的帮助
答案 0 :(得分:4)
另一个选择是使用自定义pl / sql函数。
CREATE OR REPLACE FUNCTION "STR_TO_TABLE"
(in_strt in varchar2,
in_delim in varchar2 default ',')
return str_table
as
l_str clob default in_strt || in_delim;
l_n number;
l_data str_table := str_table();
begin
loop
l_n := instr( l_str, in_delim );
exit when (nvl(l_n,0) = 0);
l_data.extend;
l_data( l_data.count ) := ltrim(rtrim(substr(l_str,1,l_n-1)));
l_str := substr( l_str, l_n+length(in_delim) );
end loop;
return l_data;
end;
/
create or replace function custom_concat(col1 varchar2,col2 varchar2)
return varchar2
is
conct_val varchar2(4000);
begin
select listagg(final, ' ') within group (order by 1) into conct_val from (
select r1,M.column_value mcv,s.column_value scv,s.s1,M.column_value||','||s.column_value final from (select rownum r1,column_value from table(STR_TO_TABLE(col1))) M join (select rownum s1,column_value from table(STR_TO_TABLE(col2))s1) s on (r1=s1) );
return conct_val;
end;
/
然后像这样使用它-
select col1,col2,custom_concat(col1,col2) from temp_123;
结果-
答案 1 :(得分:4)
根据Matthew的要求,使用相同的扩展样本数据,将11gR2兼容版本分解为逗号分隔的列表:
with input_data ( id, col1, col2 ) as (
SELECT 1 , '1,2,3,4', 'V1,V2,V3,V4' from dual union all
SELECT 2 , '4,5,6,7', 'V5,V6,V7,V8' from dual union all
SELECT 3 , 'A', 'VA,VB,VC,VD' from dual union all
SELECT 4 , 'E,F,G', 'VE' from dual union all
SELECT 5 , 'H,I', '' from dual union all
SELECT 6 , '', 'J,K' from dual
)
, cte (id, col1, col2, pos, combined_value) as (
select id, col1, col2, level,
regexp_substr(col1, '(.*?)(,|$)', 1, level, null, 1)
||','|| regexp_substr(col2, '(.*?)(,|$)', 1, level, null, 1)
from input_data
connect by id = prior id
and prior dbms_random.value is not null
and level <= greatest(nvl(regexp_count(col1, ','), 0),
nvl(regexp_count(col2, ','), 0)) + 1
)
select id,
col1,
col2,
listagg(combined_value, ' ') within group (order by pos) as col3
from cte
group by id, col1, col2;
ID COL1 COL2 COL3
---------- ------- ----------- ------------------------------
1 1,2,3,4 V1,V2,V3,V4 1,V1 2,V2 3,V3 4,V4
2 4,5,6,7 V5,V6,V7,V8 4,V5 5,V6 6,V7 7,V8
3 A VA,VB,VC,VD A,VA ,VB ,VC ,VD
4 E,F,G VE E,VE F, G,
5 H,I H, I,
6 J,K ,J ,K
附加的CTE将适当的列值转换为单独编号的列表,这些编号针对列表中的每个ID和位置串联在一起。就像在Matthew的答案中一样,每个ID的所有串联值都汇总到一个以空格分隔的字符串中。
但是,返回到当前视图的源仍会更简单,也可能更有效率-假设它本身是通过字符串聚合创建col1
和col2
值的-并且新查询/对该原始查询的查看。
在其他视图之上构建视图可能会导致性能问题,因为优化器无法始终将谓词传递到正确的位置。但是,创建汇总的值列表,将其拆分,然后重新汇总它们的工作量超出了您的需要。
答案 2 :(得分:2)
您需要将以逗号分隔的col1
和col2
值分成几行,然后将每一行连接起来,然后将这些连接按逗号分隔的字符串汇总回一。
使用众所周知的技巧来完成拆分:使用CONNECT BY
为列表中的每个条目生成一个“虚拟”行,然后使用REGEXP_SUBSTR
来选择每个逗号分隔的值。
通过LISTAGG
完成滚动。
这是全部(加上额外的测试数据以解决每一列中元素数量的不匹配):
with input_data ( id, col1, col2 ) as (
SELECT 1 , '1,2,3,4', 'V1,V2,V3,V4' from dual union all
SELECT 2 , '4,5,6,7', 'V5,V6,V7,V8' from dual union all
SELECT 3 , 'A', 'VA,VB,VC,VD' from dual union all
SELECT 4 , 'E,F,G', 'VE' from dual union all
SELECT 5 , 'H,I', '' from dual union all
SELECT 6 , '', 'J,K' from dual
)
select i.id,
i.col1,
i.col2,
listagg(trim(regexp_substr(i.col1, '[^,]+', 1, p.pos)) ||
',' || trim(regexp_substr(i.col2, '[^,]+', 1, p.pos)),',')
within group ( order by p.pos ) col3
from input_data i
cross apply ( select rownum pos
FROM dual
connect by level <=
greatest(nvl(regexp_count(i.col1,','),0),
nvl(regexp_count(i.col2,','),0)) +1 ) p
group by i.id, i.col1, i.col2;
结果:
+----+---------+-------------+---------------------+
| ID | COL1 | COL2 | COL3 |
+----+---------+-------------+---------------------+
| 1 | 1,2,3,4 | V1,V2,V3,V4 | 1,V1,2,V2,3,V3,4,V4 |
| 2 | 4,5,6,7 | V5,V6,V7,V8 | 4,V5,5,V6,6,V7,7,V8 |
| 3 | A | VA,VB,VC,VD | A,VA,,VB,,VC,,VD |
| 4 | E,F,G | VE | E,VE,F,,G, |
| 5 | H,I | | H,,I, |
| 6 | | J,K | ,J,,K |
+----+---------+-------------+---------------------+
答案 3 :(得分:1)
您需要为每行在PLSQL(或更大的sql查询)中进行操作:
这是拆分方法的完成方式:
SELECT num_value
FROM (SELECT TRIM (REGEXP_SUBSTR (num_csv, '[^,]+', 1, LEVEL)) num_value
FROM ( SELECT col1 num_csv FROM table_view)
CONNECT BY LEVEL <= regexp_count (num_csv, ',', 1) + 1)