【问题标题】:Parse Full Name Field Oracle解析全名字段 Oracle
【发布时间】:2020-01-18 03:12:46
【问题描述】:

我想知道是否有人可以帮助我解析全名字段。 我想把它分成姓氏、名字、中间名首字母、后缀。

这里有一些名称输入,然后是我希望如何解析它们。

                           Parsed Stuff Begins Here-------------------------------------
    name                  | lastname  | firstname        |  middle initial   | suffix |
----------------------------------------------------------------------------------------
PUBLIC, JOHN              | PUBLIC    | JOHN             |  NULL             | NULL
PUBLIC, CHUN CH KIM       | PUBLIC    | CHUN CH KIM      |  NULL             | NULL
PUBLIC, MARY L            | PUBLIC    | MARY             |  L                | NULL
PUBLIC, FRED J JR         | PUBLIC    | FRED             |  J                | JR
PUBLIC, SUE ELLEN J SR    | PUBLIC    | SUE ELLEN        |  J                | SR

我有一个可以输入的所有后缀值的列表,即

JR, SR, I,II,III,IV,V,VI

我已经到了将姓氏和其他名字分开的地步, 但我不知道如何做剩下的。 我正在使用 oracle 10g。

这不是作业问题。这是我在工作中正在解决的一个实际问题。

这是我目前拥有的:

 select id,
        name,
        substr(name,1, instr(name,',')-1) as lname,
        substr(name,(instr(name,',')+1),length(name)) as rest_of_the_name
 from    my_table
 where status='A';

【问题讨论】:

  • 如果您向我们展示您拥有的东西,而不仅仅是问题陈述,这可能会有所帮助。我重复“这是作业吗”的问题。

标签: parsing oracle10g


【解决方案1】:

这是一个总会有数据破坏它的问题。

如果有 2 个首字母怎么办?如果首字母在前,比如 J Edgar Hoover,会怎样?

您提到“可以输入的值”。您可以更改输入值的方式以捕获已经分离的值吗?

【讨论】:

  • 是的,我们正计划改变它们的输入方式,以便它们都被捕获在不同的字段中,但目前存在大约 500 万个名称需要解析。
  • +1 以获得最佳建议 - 首先尝试捕获分隔的值。
【解决方案2】:

您已经部分解决了 - 您可以将查询用作子查询并逐点分解问题,例如:

select id, name, lname,
       case
       when substr(x, -2, 1) = ' '
       then substr(x, length(x) - 2)
       else x
       end as first_name, -- e.g. "SUE ELLEN"
       case
       when substr(x, -2, 1) = ' ' 
       then substr(x, -1)
       else null
       end as middle_initial, -- e.g. "J"
       suffix -- e.g. "SR"
from (
select id, name, lname, suffix,
       case when suffix is not null then
       substr(rest_of_the_name, 1, length(rest_of_the_name)-length(suffix)-1)
       else rest_of_the_name end
       as x -- e.g. "SUE ELLEN J"
from (
select id, name, lname, rest_of_the_name,
       case
       when substr(rest_of_the_name,-2)
            in (' I',' V')
       then substr(rest_of_the_name,-1)
       when substr(rest_of_the_name,-3)
            in (' JR',' SR',' II',' IV',' VI')
       then substr(rest_of_the_name,-2)
       when substr(rest_of_the_name,-4)
            in (' III')
       then substr(rest_of_the_name,-3)
       else null
       end as suffix -- e.g. "SR"
from (
select id,
       name, --e.g. "PUBLIC, SUE ELLEN J SR"
       trim(substr(name,1, instr(name,',')-1)) as lname, -- e.g. "PUBLIC"
       trim(substr(name,(instr(name,',')+1),length(name)))
          as rest_of_the_name -- e.g. "SUE ELLEN J SR"
from    my_table
where status='A'
)));

【讨论】:

  • 谢谢杰弗里!我稍微改变了查询,最终得到了一个适用于我们数据库中大多数名称的解决方案。
  • 您可能会发现您必须根据数据的一致性不断对其进行相当多的更改 - 以使使用程序解决方案更容易。
  • Jeffrey Kemp 提到 OP 可能需要一个程序解决方案。有没有可能有人已经创建了一个?
【解决方案3】:

这是一个简单的答案,基于检索名字和姓氏,以与名字相同的方式检索 MI,从 'rest_of_the_name' 中删除 MI 作为姓氏。

SELECT
substr('John Q. Public',1, instr('John Q. Public',' ')-1) as FirstName,
substr('John Q. Public',(instr('John Q. Public',' ')+1),length('John Q. Public')) as rest_of_the_name,
substr(substr('John Q. Public',(instr('John Q. Public',' ')+1),length('John Q. Public')),1, instr(substr('John Q. Public',(instr('John Q. Public',' ')+1),length('John Q. Public')),' ')-1) as MI,
replace(substr('John Q. Public',(instr('John Q. Public',' ')+1),length('John Q. Public')), substr(substr('John Q. Public',(instr('John Q. Public',' ')+1),length('John Q. Public')),1, instr(substr('John Q. Public',(instr('John Q. Public',' ')+1),length('John Q. Public')),' ')-1)) as LastName
FROM DUAL;

【讨论】:

    【解决方案4】:

    这篇文章包含一个非常完整的纯 SQL 解决方案,用 SQLServer 语法编写。我已将其转换为 Oracle 语法。它做得很好,虽然它不处理后缀(Jr.、III 等)。您应该阅读帖子中的其他警告:

    SQL: parse the first, middle and last name from a fullname field

    SELECT first_name.original_input_data,
           first_name.title,
           first_name.first_name,
           CASE
               WHEN 0 = INSTR(first_name.rest_of_name, ' ') THEN
                NULL --no more spaces?  assume rest is the last name
               ELSE
                SUBSTR(first_name.rest_of_name, 1, INSTR(first_name.rest_of_name, ' ') - 1)
           END AS middle_name,
           SUBSTR(first_name.rest_of_name,
                  1 + INSTR(first_name.rest_of_name, ' '),
                  LENGTH(first_name.rest_of_name)) AS last_name
      FROM (SELECT title.title,
                    CASE
                        WHEN 0 = INSTR(title.rest_of_name, ' ') THEN
                         title.rest_of_name --No space? return the whole thing
                        ELSE
                         SUBSTR(title.rest_of_name, 1, INSTR(title.rest_of_name, ' ') - 1)
                    END AS first_name,
                    CASE
                        WHEN 0 = INSTR(title.rest_of_name, ' ') THEN
                         NULL --no spaces @ all?  then 1st name is all we have
                        ELSE
                         SUBSTR(title.rest_of_name, INSTR(title.rest_of_name, ' ') + 1, LENGTH(title.rest_of_name))
                    END AS rest_of_name,
                    title.original_input_data
               FROM (SELECT
                      --if the first three characters are in this list,
                      --then pull it as a "title".  otherwise return NULL for title.
                       CASE
                           WHEN SUBSTR(test_data.full_name, 1, 3) IN ('MR ', 'MS ', 'DR ', 'MRS') THEN
                            LTRIM(RTRIM(SUBSTR(test_data.full_name, 1, 3)))
                           ELSE
                            NULL
                       END AS title
                       --if you change the list, don't forget to change it here, too.
                     --so much for the DRY prinicple...
                    ,
                     CASE
                         WHEN SUBSTR(test_data.full_name, 1, 3) IN ('MR ', 'MS ', 'DR ', 'MRS') THEN
                          LTRIM(RTRIM(SUBSTR(test_data.full_name, 4, LENGTH(test_data.full_name))))
                         ELSE
                          LTRIM(RTRIM(test_data.full_name))
                     END AS rest_of_name,
                     test_data.original_input_data
                      FROM (SELECT
                            --trim leading & trailing spaces before trying to process
                            --disallow extra spaces *within* the name
                             REPLACE(REPLACE(LTRIM(RTRIM(full_name)), '  ', ' '), '  ', ' ') AS full_name,
                             full_name AS original_input_data
                              FROM ( --if you use this, then replace the following
                                    --block with your actual table
                                    SELECT 'george w bush jr.' AS full_name
                                      FROM dual
                                    UNION
                                    SELECT 'SUSAN B ANTHONY' AS full_name
                                      FROM dual
                                    UNION
                                    SELECT 'alexander hamilton' AS full_name
                                      FROM dual
                                    UNION
                                    SELECT 'osama bin laden jr' AS full_name
                                      FROM dual
                                    UNION
                                    SELECT 'Martin J. VAN BUREN SENIOR III' AS full_name
                                      FROM dual
                                    UNION
                                    SELECT 'Tommy' AS full_name
                                      FROM dual
                                    UNION
                                    SELECT 'Billy' AS full_name
                                      FROM dual
                                    UNION
                                    SELECT NULL AS full_name
                                      FROM dual
                                    UNION
                                    SELECT ' ' AS full_name
                                      FROM dual
                                    UNION
                                    SELECT '    JOHN  JACOB     SMITH' AS full_name
                                      FROM dual
                                    UNION
                                    SELECT ' DR  SANJAY       GUPTA' AS full_name
                                      FROM dual
                                    UNION
                                    SELECT 'DR JOHN S HOPKINS' AS full_name
                                      FROM dual
                                    UNION
                                    SELECT ' MRS  SUSAN ADAMS' AS full_name
                                      FROM dual
                                    UNION
                                    SELECT ' MS AUGUSTA  ADA   SMITH-KING ' AS full_name
                                      FROM dual) raw_data) test_data) title) first_name
    

    【讨论】:

      【解决方案5】:

      选择 SUBSTR(name, INSTR(name, ' ')+1) AS lastname, SUBSTR(name, 1, INSTR(name, ' ')-1) 作为名字 随便;

      【讨论】:

        猜你喜欢
        • 2020-04-01
        • 2022-12-09
        • 2019-05-07
        • 2010-09-14
        • 2020-08-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多