我遇到oracle拆分查询问题。
在oracle查询中使用connect by和regular expression将逗号分隔数据拆分为多行时,我得到更多重复行。例如,实际上我的表有150行,在那两行中有逗号分隔的字符串,所以整体上我只得到155行,但我得到2000行。如果我使用distinct它的工作正常,但我不想在查询结果中重复行。
我尝试了以下查询,但它在查询结果中生成了重复的行:
WITH CTE AS (SELECT 'a,b,c,d,e' temp,1 slno FROM DUAL
UNION
SELECT 'f,g',2 from dual
UNION
SELECT 'h',3 FROM DUAL)
SELECT TRIM(REGEXP_SUBSTR( TEMP, '[^,]+', 1, LEVEL)) ,SLNO FROM CTE
CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE(temp, '[^,]+')) + 1
修改
上述选择查询只能拆分单个逗号分隔字符串,但是,当在多行的表上执行时,它会生成重复行。如何限制重复的行?
答案 0 :(得分:7)
最后我想出了这个答案
WITH CTE AS (SELECT 'a,b,c,d,e' temp, 1 slno FROM DUAL
UNION
SELECT 'f,g' temp, 2 slno FROM DUAL
UNION
SELECT 'h' temp, 3 slno FROM DUAL)
SELECT TRIM(REGEXP_SUBSTR(temp, '[^,]+', 1, level)), slno
FROM CTE
CONNECT BY level <= REGEXP_COUNT(temp, '[^,]+')
AND PRIOR slno = slno
AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL
答案 1 :(得分:5)
试试这个,
WITH CTE AS (SELECT 'a,b,c,d,e' temp,1 slno FROM DUAL
UNION
SELECT 'f,g',2 from dual
UNION
SELECT 'h',3 FROM DUAL)
SELECT regexp_substr (temp, '[^,]+', 1, rn)temp, slno
FROM cte
CROSS JOIN
(
SELECT ROWNUM rn
FROM (SELECT MAX (LENGTH (regexp_replace (temp, '[^,]+'))) + 1 max_l
from cte
)
connect by level <= max_l
)
WHERE regexp_substr (temp, '[^,]+', 1, rn) IS NOT NULL
order by temp;
答案 2 :(得分:2)
接受的答案使用不合适的条件DBMS_RANDOM.VALUE IS NOT NULL
。它只是阻止了循环循环,但是一个直接的问题会出现为 dbms_random.VALUE
如何以及何时可以为空?从逻辑上讲,它永远不会是 NULL 。
更合适的解决方案是使用 sys.odciNumberList 并阻止循环循环。
例如,
设置
SQL> CREATE TABLE t (
2 ID NUMBER GENERATED ALWAYS AS IDENTITY,
3 text VARCHAR2(100)
4 );
Table created.
SQL>
SQL> INSERT INTO t (text) VALUES ('word1, word2, word3');
1 row created.
SQL> INSERT INTO t (text) VALUES ('word4, word5, word6');
1 row created.
SQL> INSERT INTO t (text) VALUES ('word7, word8, word9');
1 row created.
SQL> COMMIT;
Commit complete.
SQL>
SQL> SELECT * FROM t;
ID TEXT
---------- ----------------------------------------------
1 word1, word2, word3
2 word4, word5, word6
3 word7, word8, word9
SQL>
必填查询:
SQL> SELECT t.id,
2 trim(regexp_substr(t.text, '[^,]+', 1, lines.column_value)) text
3 FROM t,
4 TABLE (CAST (MULTISET
5 (SELECT LEVEL FROM dual CONNECT BY LEVEL <= regexp_count(t.text, ',')+1)
6 AS sys.odciNumberList
7 )
8 ) lines
9 ORDER BY id
10 /
ID TEXT
---------- --------------------------------------------------
1 word1
1 word2
1 word3
2 word4
2 word5
2 word6
3 word7
3 word8
3 word9
9 rows selected.
使用XMLTABLE
的替代解决方案:
SQL> SELECT id,
2 trim(COLUMN_VALUE) text
3 FROM t,
4 xmltable(('"'
5 || REPLACE(text, ',', '","')
6 || '"'))
7 /
ID TEXT
---------- ------------------------
1 word1
1 word2
1 word3
2 word4
2 word5
2 word6
3 word7
3 word8
3 word9
9 rows selected.
SQL>
有很多方法可以完成任务,例如 MODEL 子句。有关更多示例,请参阅Split comma delimited strings in a table
答案 3 :(得分:1)
不使用连接:
WITH CTE AS (SELECT 'a,b,c,d,e' temp,1 slno FROM DUAL
UNION
SELECT 'f,g',2 from dual
UNION
SELECT 'h',3 FROM DUAL
)
,x as (
select
','||temp||',' temp
,slno
from CTE
)
,iter as (SELECT rownum AS pos
FROM all_objects
)
select
SUBSTR(x.temp
,INSTR(x.temp, ',', 1, iter.pos) + 1
,INSTR(x.temp, ',', 1, iter.pos + 1)-INSTR(x.temp, ',', 1, iter.pos)-1
) temp
,x.slno
from x, iter
where iter.pos < = (LENGTH(x.temp) - LENGTH(REPLACE(x.temp, ','))) - 1;
答案 4 :(得分:0)
可以使用以下查询转换行中的逗号分隔值
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 );
答案 5 :(得分:0)
添加一个唯一的子句可以解决问题:
WITH cte AS (
SELECT 'a,b,c,d,e' temp, 1 slno FROM DUAL UNION
SELECT 'f,g',2 FROM DUAL UNION SELECT 'h',3 FROM DUAL
) SELECT UNIQUE(slno),REGEXP_SUBSTR(temp,'[^,]+', 1, LEVEL)temp FROM cte
CONNECT BY LEVEL<=REGEXP_COUNT(temp, '[^,]+') ORDER BY slno;