将字符串拆分为行 Oracle SQL

Posted

技术标签:

【中文标题】将字符串拆分为行 Oracle SQL【英文标题】:Split String into rows Oracle SQL 【发布时间】:2014-12-12 00:07:32 【问题描述】:

在搜索论坛后,我想出了以下内容,但它不起作用:/

我有一张桌子,上面有以下内容;

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;  

感谢任何帮助

【问题讨论】:

我能想到的唯一方法是非常低效的。在收到数据库的初始响应后,您是否有理由不能在编程语言中执行此操作? 【参考方案1】:

这应该可以解决问题:

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

请注意我是如何在 connect by 子句中使用 regexp_substr 的。这是为了处理多个空格的情况。


如果您对每行的项目数有一个可预测的上限,则可能值得将上述递归查询的性能与简单的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 进行现场演示

【讨论】:

这就是我的想法,但它似乎不接受“”中的属性字符串它告诉我它是一个无效的标识符 @Grant “属性字符串 [...] 它告诉我它的标识符无效” FWIW,当引用时,标识符区分大小写。也许这是你的问题?还是一个简单的错字?如果不是,那就很奇怪了?!?如果您自己无法修复,也许值得问一个其他问题,只关注该问题,并提及您的表的确切结构、您尝试的查询以及非常精确的错误代码和由您的 Oracle 版本。 很好,我得到了这个工作谢谢这是我的错字 @SylvainLeroux 您可以使用sys.odciNumberList 和简单的连接消除对每行项目数可预测性的依赖。还有许多其他方法,但是,性能可能是一个因素。你可以看看Split comma delimited strings in a table。我也在回答中添加了一些示例。【参考方案2】:

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

不依赖于每行项目数的可预测性。 不依赖于 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>

【讨论】:

【参考方案3】:
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 

【讨论】:

实际上大约有 20000 行,所以我需要一种方法来拆分所有字符串 “WITH T as(...) 只是为了创建您显示的测试数据。所以主要查询将是“Select Distinct.... From myTable...”之类的东西. 但是老实说,另一个答案更好

以上是关于将字符串拆分为行 Oracle SQL的主要内容,如果未能解决你的问题,请参考以下文章

Oracle SQL - 如何将逗号拆分限制为行

将字符串拆分为行

Redshift :- 易于将逗号分隔的字符串拆分为行

将字符串拆分为行的最佳方法

如何在不破坏单词的情况下将字符串拆分为行?

BigQuery 将“字节”列拆分为行