2014-10-16 123 views
4

在搜索论坛后,我想出了以下内容,但它不起作用:/将字符串拆分成行Oracle SQL

我有一个表格,

ID | Strings  
123| abc fgh dwd 
243| dfs dfd dfg 
353| dfs 
424| dfd dfw 
523|  
. 
. 
. 

请不有大约20,000行我的另一种选择是写一个存储过程做到这一点...基本上,我需要拆分串起来所以为每一个这样的

ID | Strings 
123| abc 
123| fgh 
123| dwd 
243| dfs 

等等...

这就是我。

create table Temp AS 
SELECT ID, strings 
From mytable; 

SELECT DISTINCT ID, trim(regexp_substr(str, '[^ ]+', 1, level)) str 
FROM (SELECT ID, strings str FROM temp) t 
CONNECT BY instr(str, ' ', 1, level -1) >0 
ORDER BY ID; 

任何帮助表示赞赏

+0

我能想到这样做将是非常低效的唯一途径。在接收到数据库的初始响应后,您是否有理由在编程语言中无法做到这一点? – Sam 2014-10-16 15:57:13

回答

5

这应该做的伎俩:

SELECT DISTINCT ID, regexp_substr("Strings", '[^ ]+', 1, LEVEL) 
FROM T 
CONNECT BY regexp_substr("Strings", '[^ ]+', 1, LEVEL) IS NOT NULL 
ORDER BY ID; 

通知我如何在连接使用regexp_substr by子句了。这是为了处理多空间的情况。


如果您对每行项目的数量可预测的上限,则可能值得用一个简单的CROSS JOIN比较递归查询的性能上面:

WITH N as (SELECT LEVEL POS FROM DUAL CONNECT BY LEVEL < 10) 
--              ^^ 
--             up to 10 substrings 
SELECT ID, regexp_substr("Strings", '[^ ]+', 1, POS) 
FROM T CROSS JOIN N 
WHERE regexp_substr("Strings", '[^ ]+', 1, POS) IS NOT NULL 
ORDER BY ID; 

了现场见http://sqlfiddle.com/#!4/444e3/1演示

+0

这是我以为这样做的,但它似乎并不接受属性字符串在“”它告诉我它的无效标识符 – 2014-10-17 00:45:50

+0

@Grant _“属性字符串[... ]它告诉我它是一个无效的标识符“_ FWIW,当引用时,标识符区分大小写。也许这是你的问题?或者是一个简单的错字?如果不是,那很奇怪?!?如果你无法自己修复它,也许值得另辟蹊径,只关注这个问题,并提及你的表的确切结构,试图查询以及由你的Oracle版本生成的非常准确的错误代码和消息。 – 2014-10-17 08:05:37

+1

所有好的我得到了这个工作谢谢这是我的错字 – 2014-10-19 04:21:47

-1
With T As 
     (select 123 as id, 'abc fgh dwd' as strings from dual 

     union 

     select 243 as id, 'dfs dfd dfg' as strings from dual 

     union 

     Select 353 As Id, 'dfs' As Strings From Dual 

     union 

     select 424 as id, 'dfd dfw' as strings from dual 


    ) 


select distinct id, REGEXP_SUBSTR (Replace(Strings, ' ', ','), '[^,]+', 1, level) as Strings 
from t 
Connect By Level <= Length(Regexp_Replace(Replace(Strings, ' ', ','),'[^,]*'))+1 
order by id, strings; 


**********OUTPUT************* 
     ID STRINGS 
---------- ----------- 
    123 abc  
    123 dwd 
    123 fgh  
    243 dfd  
    243 dfg  
    243 dfs  
    353 dfs  
    424 dfd  
    424 dfw  

9 rows selected 
+0

实际上有大约20000行,所以我需要一种方法来分割所有的字符串 – 2014-10-17 01:50:49

+0

“WITH T as(...)只是为了创建你展示的测试数据。所以主要的查询将是“Select Distinct .... From myTable ...”这样的事情。然而,其他答案是坦率地更好 – Steve 2014-10-17 12:55:35

3

更灵活,更好的解决方案:

  • 不依赖于每行项目数量的可预测性。
  • 不依赖于ID列,解决方案给出正确的结果,而不考虑列的数量。
  • 甚至不取决于DISTINCT关键字。

有使用XMLTABLEMODEL子句其他例子,请阅读Split comma delimited strings in a table

例如,

没有ID列:

SQL> WITH T AS 
    2 (SELECT 'abc fgh dwd' AS text FROM dual 
    3 UNION 
    4 SELECT 'dfs dfd dfg' AS text FROM dual 
    5 UNION 
    6 SELECT 'dfs' AS text FROM Dual 
    7 UNION 
    8 SELECT 'dfd dfw' AS text FROM dual 
    9 ) 
10 SELECT trim(regexp_substr(t.text, '[^ ]+', 1, lines.column_value)) text 
11 FROM t, 
12 TABLE (CAST (MULTISET 
13 (SELECT LEVEL FROM dual CONNECT BY instr(t.text, ' ', 1, LEVEL - 1) > 0 
14 ) AS sys.odciNumberList)) lines 
15/

TEXT 
----------- 
abc 
fgh 
dwd 
dfd 
dfw 
dfs 
dfs 
dfd 
dfg 

9 rows selected. 

随着ID列:

SQL> WITH T AS 
    2 (SELECT 123 AS id, 'abc fgh dwd' AS text FROM dual 
    3 UNION 
    4 SELECT 243 AS id, 'dfs dfd dfg' AS text FROM dual 
    5 UNION 
    6 SELECT 353 AS Id, 'dfs' AS text FROM Dual 
    7 UNION 
    8 SELECT 424 AS id, 'dfd dfw' AS text FROM dual 
    9 ) 
10 SELECT id, trim(regexp_substr(t.text, '[^ ]+', 1, lines.column_value)) text 
11 FROM t, 
12 TABLE (CAST (MULTISET 
13 (SELECT LEVEL FROM dual CONNECT BY instr(t.text, ' ', 1, LEVEL - 1) > 0 
14 ) AS sys.odciNumberList)) lines 
15 ORDER BY id 
16 /

     ID TEXT 
---------- ----------- 
     123 abc 
     123 fgh 
     123 dwd 
     243 dfs 
     243 dfd 
     243 dfg 
     353 dfs 
     424 dfd 
     424 dfw 

9 rows selected. 

SQL>