Sql Oracle查询解析名称的后缀

Sql Oracle查询解析名称的后缀,sql,oracle,Sql,Oracle,我有全名lastname,firstname middlename,包括一个字段中的后缀。下面是解析名称的业务规则 。姓氏:从第一个位置到逗号的字符将出现在姓氏中。 . 名字:逗号到下一个空格后的第一个字符将转到名字。 . 后缀:派生出名字和姓氏后,根据值Jr、Sr、II、III、IV、V在名称短语的剩余部分搜索后缀名称 . 中间名:将其余字符放入中间名 LST,FRST MDL SR她的LST是姓,FRST是名,MDL是中间名,SR后缀 LST,first SR MDL MDL2她的LST是L

我有全名lastname,firstname middlename,包括一个字段中的后缀。下面是解析名称的业务规则


。姓氏:从第一个位置到逗号的字符将出现在姓氏中。 . 名字:逗号到下一个空格后的第一个字符将转到名字。 . 后缀:派生出名字和姓氏后,根据值Jr、Sr、II、III、IV、V在名称短语的剩余部分搜索后缀名称 . 中间名:将其余字符放入中间名

LST,FRST MDL SR她的LST是姓,FRST是名,MDL是中间名,SR后缀 LST,first SR MDL MDL2她的LST是LastName,first是FirstName,MDL MDL2是middleName,SR后缀 第一个MDL1 JR MDL2 MDL3她的第一个是姓,第一个是名,第二个MDL1 MDL2 MDL3是中间名,JR后缀 表示各种格式的后缀和中间名。是否可以编写一个查询来提取后缀,并将其余部分放入中间名称字段

这是我的查询,但我正在寻找更简单的方法,而且我的查询是检查中间名中最多3个空格以查找后缀

WITH IDN_NAM AS
(
 SELECT RECORD_NUMBER, IDN.INDEX1,
  trim(regexp_substr(REPLACE(IDN.IDN_NAM,',',' '),  '[^ ]+',1,2)) AS FIRST_NAME,
  trim(regexp_substr(REPLACE(IDN.IDN_NAM,',',' '),  '[^ ]+',1,1)) AS LAST_NAME,
  CASE WHEN instr(REPLACE(IDN.IDN_NAM,',',' '),' ',1,2)+1 = 1 THEN NULL ELSE substr(REPLACE(IDN.IDN_NAM,',',' '),instr(REPLACE(IDN.IDN_NAM,',',' '),' ',1,2)+1) END AS MID_NAME,
  TRIM(IDN.IDN_NAM) AS FULL_NAME
  FROM 
  (
   SELECT IDN.RECORD_NUMBER, IDN_NAM IDN_NAM_ORIG, replace(replace(replace(REPLACE(IDN.IDN_NAM, ',', ' '),' ','<>'),'><',''),'<>',' ') IDN_NAM , IDN.INDEX1
   FROM SNM_TMP_IDENTITY_IDN_NAM IDN,
        TMP_LEGACY_EVENT T
   WHERE IDN.RECORD_NUMBER = T.RECORD_NUMBER 
    AND NOT REGEXP_LIKE(IDN_NAM,'DLE.+[[:digit:]]')
  ) IDN
)
SELECT DECODE(INDEX1, 1, 'T', 'F') MASTER_IND, FIRST_NAME, LAST_NAME,--, MID_NAME, MID_NAM1, MID_NAM2, MID_NAM3, SUF1, SUF2, SUF3,
CASE WHEN SUF3 IS NULL AND SUF2 IS NULL AND SUF1 IS NULL THEN MID_NAME
    WHEN SUF3 IS NOT NULL THEN NVL(MID_NAM1,'')||CASE WHEN MID_NAM2 IS NOT NULL THEN ' '||MID_NAM2 ELSE '' END
    WHEN SUF2 IS NOT NULL THEN NVL(MID_NAM1,'')||CASE WHEN MID_NAM3 IS NOT NULL THEN ' '||MID_NAM3 ELSE '' END
    WHEN SUF1 IS NOT NULL THEN NVL(MID_NAM2,'')||CASE WHEN MID_NAM3 IS NOT NULL THEN ' '||MID_NAM3 ELSE '' END
END MIDDLE_NAME,
NVL(SUF3, NVL(SUF2, SUF1)) NAME_SUFFIX_CD
FROM
(
SELECT NM.*,
(SELECT MAX(NAME_SUFFIX_CODE) FROM CRRMS_CODED.CODED_NAME_SUFFIX WHERE UPPER(REPLACE(NAME_SUFFIX_CODE,'.', '')) = UPPER(MID_NAM1)) SUF1,
(SELECT MAX(NAME_SUFFIX_CODE) FROM CRRMS_CODED.CODED_NAME_SUFFIX WHERE UPPER(REPLACE(NAME_SUFFIX_CODE,'.', '')) = UPPER(MID_NAM2)) SUF2,
(SELECT MAX(NAME_SUFFIX_CODE) FROM CRRMS_CODED.CODED_NAME_SUFFIX WHERE UPPER(REPLACE(NAME_SUFFIX_CODE,'.', '')) = UPPER(MID_NAM3)) SUF3
FROM
(
 SELECT I.*,
  trim(regexp_substr(MID_NAME,  '[^ ]+',1,1)) AS MID_NAM1,
  trim(regexp_substr(MID_NAME,  '[^ ]+',1,2)) AS MID_NAM2,
  trim(regexp_substr(MID_NAME,  '[^ ]+',1,3)) AS MID_NAM3
 FROM IDN_NAM I
) NM
)
;

这里有一个查询可能符合要求,但它稍微超出了问题定义,因为它还处理前缀:

with names(name) as (
            select 'LST, FRST MDL SR' from dual
  union all select 'LST, FRST SR MDL MDL2' from dual
  union all select 'LST, FRST MDL1 JR MDL2 MDL3' from dual
  union all select 'Jones, John Paul' from dual
  union all select 'Jones, Mr. John Jr Paul' from dual
  union all select 'Jones, John Paul Jr Henry' from dual
  union all select 'Henry, John Paul Sr' from dual
  union all select 'Masters, Lee II' from dual
)
select name
     , REGEXP_SUBSTR(name, '([^,]+), ?(((dr|rev|mr|mrs|ms|miss)[.]?) )?([^ ]+) ?(.*)',1,1,'i',3) pfx
     , REGEXP_SUBSTR(name, '([^,]+), ?(((dr|rev|mr|mrs|ms|miss)[.]?) )?([^ ]+) ?(.*)',1,1,'i',5) frst
     , rtrim(REGEXP_REPLACE(
       REGEXP_SUBSTR(name, '([^,]+), ?(((dr|rev|mr|mrs|ms|miss)[.]?) )?([^ ]+) ?(.*)',1,1,'i',6)
       ,'(^|[[:space:]])(jr|sr|ii|iii|iv|v)([[:space:]]|$)','\1',1,1,'i')) mdl
     , REGEXP_SUBSTR(name, '([^,]+), ?(((dr|rev|mr|mrs|ms|miss)[.]?) )?([^ ]+) ?(.*)',1,1,'i',1) Lst
     , REGEXP_SUBSTR(
       REGEXP_SUBSTR(name, '([^,]+), ?(((dr|rev|mr|mrs|ms|miss)[.]?) )?([^ ]+) ?(.*)',1,1,'i',6)
       ,'(^|[[:space:]])(jr|sr|ii|iii|iv|v)([[:space:]]|$)',1,1,'i',2) SFX
from names;
如果您不需要前缀,则这可能适用于您:

select name
     , REGEXP_SUBSTR(name, '([^,]+), ?([^ ]+) ?(.*)',1,1,'i',2) frst
     , rtrim(REGEXP_REPLACE(
       REGEXP_SUBSTR(name, '([^,]+), ?([^ ]+) ?(.*)',1,1,'i',3)
       ,'(^|[[:space:]])(jr|sr|ii|iii|iv|v)([[:space:]]|$)','\1',1,1,'i')) mdl
     , REGEXP_SUBSTR(name, '([^,]+), ?([^ ]+) ?(.*)',1,1,'i',1) Lst
     , REGEXP_SUBSTR(
       REGEXP_SUBSTR(name, '([^,]+), ?([^ ]+) ?(.*)',1,1,'i',3)
       ,'(^|[[:space:]])(jr|sr|ii|iii|iv|v)([[:space:]]|$)',1,1,'i',2) SFX
from names;
始终使用相同的正则表达式来标识和提取名称的每个部分:

'([^,]+), ?([^ ]+) ?(.*)'
 |     |   |     |  +--+ -> 3) Middle Names (including Suffix)
 |     |   +-----+ -------> 2) First Name
 +-----+ -----------------> 1) Last Name
名字和姓氏都是直截了当的。但是,中间的名称和后缀需要一些额外的工作来管理。要仅获取中间名称或后缀,需要第二个正则表达式:

'(^|[[:space:]])(jr|sr|ii|iii|iv|v)([[:space:]]|$)'
通过使用上述正则表达式和REGEXP_REPLACE函数,可以删除后缀,只留下中间名。同样地,使用相同的regexp和regexp_SUBSTR函数可以检索后缀本身。

Din

获取3个示例输入,并根据逻辑进行查询,以获取姓氏、名、后缀和中间名。对于所有3个,它都很好

select last_name,first_name,suffix
,trim(regexp_replace(input_string,'(^'||last_name||',|'||first_name||'|'||suffix||')',' ',1,0,'i')) as middle_name
from (
select substr(col,1,instr(col,',',1,1)-1) as last_name ,
trim(substr(col,instr(col,',',1,1)+1,instr(col,' ',1,1))) as first_name,
trim(regexp_substr(col,'(Jr|Sr|II|III|IV|V)',1,1,'i')) as suffix,
col as input_string
from (
select 'LST, FRST MDL1 JR MDL2 MDL3' as col from dual));

请提供一些数据示例、输入结构以及您希望看到的最终结果。仅提供查询就很难将问题可视化。很抱歉,我忘了提及,我可以像LST FRST MDL SR一样获得没有逗号的名称。当我应用您的查询时,它没有返回任何内容。在本例中,我希望第一个字符以空格作为姓氏,然后从空格到下一个空格作为姓氏,其余为中间名和后缀的相同业务规则。谢谢您的帮助。姓氏:从第一个位置到逗号的字符如果逗号不可用,则直到第一个空格都将使用姓氏。名字:逗号或第一个空格后到下一个空格的第一个字符将转到名字。后缀:派生出名字和姓氏后,根据值Jr、Sr、II、III、IV、V在名称短语的剩余部分搜索后缀名称。中间名:将其余字符放在中间名中。谢谢大家的帮助。这对我有用。谢谢。