将字符串拆分为两列(SQL或PL / SQL)

时间:2012-04-14 03:33:59

标签: sql string oracle

我需要将一个表中的字符串拆分为另一个表中的两列。有一些不同的数字和规则,但没有明确的分隔符。我可以使用SUBSTR和INSTR的组合,还是需要在PL / SQL中使用if-then循环来满足所有规则?

输入表

5 Kent Street 
3 A lindt Street
2/15 bold Street 
9/34-36 carmen Road
12/5a sandford Street

结果

Number  |Street
--------------------
5       |Kent Street
3A      |lindt Street
2/15    |bold Street
9/34-36 |carmen Road
12/5a   |sandford Street

2 个答案:

答案 0 :(得分:2)

我不会在pl / sql中这样做,这真的没必要。

Oracle SQL具有REGEXP_SUBSTR,REGEXP_REPLACE,REGEXP_COUNT。您还可以在SELECT子句中放入IF和CASE表达式。转到SQL参考,FUNCTIONS部分:http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions.htm#i1482196

您的数据集有一些有趣的变化 - 房屋/建筑物编号中的字母和分数。你还没有的是多个部分的街道名称(例如波士顿的Melnea Cass Boulevard)或连接/缺失(“百老汇”)或不寻常(“Cedar Passway”)街道名称的街道名称。 / p>

从sample_data开始,作为重构查询来保存输入数据。你可能会有一张桌子或视图或其他东西。

现在我们假设每个街道名称都有两个单词。我们首先使用REGEXP_COUNT计算它们。这是子查询COUNTED_DATA,其值为WORDS作为单词的计数。注意我在输入的每一行都附加一个空格,以防输入数据行的末尾没有一个空格,以便计数正确。

我搜索每个单词

[^ ]+[ ]+

即,一个或多个非空格后跟一个或多个空格。我不想使用零个或多个空格([] *),因为这是不明确的。

然后我们使用正则表达式来挑出最后两个单词和第一个单词(单词减2)单词。

结果如下:

with sample_data as (
    select '5 Kent Street' as addr from dual
    union all select '3 A lindt Street' as addr from dual
    union all select '2/15 bold Street' as addr from dual
    union all select '9/34-36 carmen Road' as addr from dual
    union all select '12/5a sandford Street' from dual
)
select 
    counted_data.addr as "Original Address",
    substr (regexp_replace (addr || ' ', '(([^ ]+[ ]+){' || (words-2) ||'})([^ ].*)','\1'), 1, 10) as "Number",
    substr (trim (regexp_replace (addr || ' ', '(([^ ]+[ ]+){' || (words-2) ||'})([^ ].*)','\3')), 1, 25) as "Street"
from
(
    select sample_data.addr, regexp_count(addr || ' ', '[ ]+') as words
    from sample_data
) counted_data

Original Address      Number     Street                   
--------------------- ---------- -------------------------
5 Kent Street         5          Kent Street               
3 A lindt Street      3 A        lindt Street              
2/15 bold Street      2/15       bold Street               
9/34-36 carmen Road   9/34-36    carmen Road               
12/5a sandford Street 12/5a      sandford Street           

为了使这个可读,我使用'substr'来减少输出列的长度。 (“COLUMN”在SQL Developer中不起作用。)

答案 1 :(得分:0)

我可以建议你三种可能性:

  1. 如果分隔字符清晰简单,请按照您的建议使用SUBSTR和INSTR的组合。

  2. 如果您的数据库支持正则表达式函数,并且您的地址字段与正则表达式匹配很简单,请使用它。例如,MySQL有REGEXP

  3. 但如果字符串的解析很复杂且变体太多,那么请使用带有完整编程语言的外部脚本。

    连接到数据库,例如在Java中,处理字符串并将结果插入新表中。如果行号很大,请记住使用批量操作,因此速度会更快。