【问题标题】:Oracle Query to parse Suffix from NameOracle查询从名称解析后缀
【发布时间】:2018-06-07 17:21:34
【问题描述】:

我在一个字段中有全名(姓氏、名字中间名,包括后缀)。这是解析名称的业务规则

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

  1. LST,FRST MDL SR(她的LST是姓氏,FRST是名字,MDL是中间名,SR后缀)
  2. LST,FRST SR MDL MDL2(她的 LST 是 LastName,FRST 是 FirstName,“MDL MDL2”是 middleName,SR 后缀)
    1. LST,FRST MDL1 JR MDL2 MDL3(她的LST是LastName,FRST是FirstName,“MDL1 MDL2 MDL3”是middleName,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
)
;

【问题讨论】:

  • 请提供一些数据示例、输入结构以及您希望如何查看最终结果。仅提供查询就很难将问题可视化。
  • 对不起,我忘了说,我可以得到没有逗号的名字,比如“LST FRST MDL SR”。当我应用您的查询时,它没有返回任何内容。我希望第一个字符以空格(在这种情况下)作为姓氏,然后从空格到下一个空格作为名字,并为中间名和后缀保留相同的业务规则。感谢您的帮助。
  • 姓:从第一个位置到逗号的字符(如果逗号不可用,则到第一个空格)将进入姓氏。名字:逗号后的第一个字符或第一个空格到下一个空格将转到名字。后缀:一旦派生了名字和姓氏,根据值 (Jr, Sr, II, III, IV, V) 在名称短语的剩余部分中搜索 Suffix name。中间名:将其余字符放入中间名。

标签: sql oracle


【解决方案1】:

这是一个符合要求的查询,尽管它超出了问题定义的范围,因为它还处理前缀:

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_SUBSTR 函数相同的正则表达式可以检索后缀本身。

【讨论】:

    【解决方案2】:

    丁,

    获取您的 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));
    

    【讨论】:

    • 感谢大家的帮助。它对我有用。欣赏它。
    猜你喜欢
    • 1970-01-01
    • 2015-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-19
    • 1970-01-01
    • 2016-06-21
    • 2013-12-21
    相关资源
    最近更新 更多