Oracle SQL 动态子串

Posted

技术标签:

【中文标题】Oracle SQL 动态子串【英文标题】:Oracle SQL Dynamic SUBSTRING 【发布时间】:2020-08-11 13:04:10 【问题描述】:

我有一个包含客户名称的列 (USERNAME)。我需要能够将其分成两列,FNAME 和 LNAME。问题是有些人的名字是双倍甚至三倍。 USERNAME 列中的名称由空格分隔。例如下图,姓氏以粗体突出显示

用户名

斯蒂芬·约翰史密斯

彼得琼斯

布莱恩·詹姆斯·安德鲁 斯宾塞

我尝试过使用 regexp_substr,但是这只是给了我直到第一个空格的数据,所以只有名字

regexp_substr(USERNAME, '[^ ]+') AS FNAME

我也尝试使用 SUBSTR 和 INSTR,我可以得到前两个名称,也可以用于三个但它不是动态的

substr(USERNAME, 1, instr(USERNAME || ' ', ' ', 2, 2) - 1) as FIRST_TWO_NAMES,

我的想法是我需要从右边开始工作,直到最后一个空格,这会给我姓氏。然后在另一个查询中再次使用此语句从原始列中提取给我可以有多个空格的名字。还是有更简单的解决方案?

【问题讨论】:

那么多个部分的姓氏呢?您真的无法区分列中的名字和姓氏。 【参考方案1】:

如果您为instr 的第三个参数提供负值,它会从字符串的末尾向后工作:

with rws as (
  select 'Stephen John Smith' usr from dual union all
  select 'Peter Jones' usr from dual union all
  select 'Brian James Andrew Spence' usr from dual
)
  select substr ( usr, 1, instr ( usr, ' ', -1 ) - 1 ) firstname,
         substr ( usr, instr ( usr, ' ', -1 ) + 1 ) lastname
  from   rws;
  
FIRSTNAME             LASTNAME   
Stephen John          Smith       
Peter                 Jones       
Brian James Andrew    Spence

【讨论】:

非常感谢,那么如果我想用这个查询从原始列中减去姓氏,给我名字,我可以减去吗? 用它从位置1到最后一个空格的位置,示例更新【参考方案2】:

您可以在REGEXP_SUSBTR() 中使用REGEXP_COUNT() 函数来确定最后一个空格的出现和提取的surname,然后在下一步使用REPLACE() 提取name 列:

WITH t AS
(
 SELECT REGEXP_SUBSTR( username, '[^ ]+',1,REGEXP_COUNT( username, '[^ ]+')) AS surname,
        username
   FROM tab 
) 
SELECT REPLACE(username,surname) AS name,
       surname
  FROM t

Demo

【讨论】:

以上是关于Oracle SQL 动态子串的主要内容,如果未能解决你的问题,请参考以下文章

sql server 里类似replace的字符串子串删除

求字符串不同子串个数

数组篇在python中如何查找最长字符串子串

如何在Java中将字符串子串到第二个点(。)?

dp求解各种子串子序列

字符串子串的查找