【问题标题】:How to query "LastName, FirstName" from "FirstName LastName" when there may be middle initials?当可能有中间名缩写时,如何从“FirstName LastName”中查询“LastName,FirstName”?
【发布时间】:2017-06-20 09:46:35
【问题描述】:

字段包含名字和姓氏。

PERSON:
Bob Franklin
Gene Smith
Roy G. Biv

我正在尝试创建一个查询,该查询将姓氏放在首位,然后是逗号,然后是名字。那部分不是问题。我遇到的问题是 Roy G. Biv。我没有返回他的姓氏,而是得到 G. Biv。我编写了一个单独的查询,可以正确返回姓氏,但我不知道如何将两者一起实现。

SELECT DISTINCT PERSON, SUBSTR(PERSON,INSTR(PERSON,' ')+1)|| ', '|| substr(person,1,INSTR(person,' ') -1) AS PERSONS
FROM LEDGER

这会返回:

Franklin, Bob
Smith, Gene
G. Biv, Roy

这个查询给了我想要的结果,来自中间名的名字:

select distinct person, SUBSTR(PERSON,INSTR(PERSON,'.')+1)
from ledger
where person like '%BIV'

返回:

Biv

结合这些的最佳方法是什么?我对 SQL 很陌生,放轻松!谢谢!

【问题讨论】:

  • 从不同的名字开始会容易得多..
  • 我同意。这是一个任务。
  • 还要考虑到有些人的名字带有空格,例如。玛丽·凯特。
  • 姓氏也可以有空格,例如Jean Claude van Damme ...您应该清楚地说明这里有哪些数据类型。
  • 规范化数据库或简单地为FNAMELNAME创建2个字段

标签: sql oracle substring


【解决方案1】:

您可以倒数搜索空格的位置。检查 INSTR here 的文档:

SELECT DISTINCT PERSON, SUBSTR(PERSON,INSTR(PERSON,' ',-1,1)+1)|| ', '|| substr(person,1,INSTR(person,' ') -1) AS PERSONS
FROM LEDGER

引用自文档:

示例 7-128 使用字符位置向后搜索找到 子串的位置

在下一个示例中,函数从最后一个倒数 字符到末尾的第三个字符,即第一个“o” 在“楼层”。然后该函数向后搜索第二个 “或”的出现,并发现第二次出现以 搜索字符串中的第二个字符。

SHOW INSTR('Corporate Floor','or', -3, 2) 
2

【讨论】:

    【解决方案2】:

    通常名称用空格分隔,因此使用 substring_index 更容易:

    SELECT 
      substring_index(PERSON, ' ', 1) AS first_name,
      substring_index(PERSON, ' ',-1) AS last_name
    FRON ledger
    

    然后如果你想重新格式化为'last_name,first_name':

    SELECT concat(
      substring_index(PERSON, ' ',-1),
      ', ',
      substring_index(PERSON, ' ', 1)
    ) AS full_name
    FRON ledger
    

    多年来,我一直在使用 first_name、last_name,有时还使用 middle_name 或 other_names 来设计用户表。

    而且我发现几乎所有时间都使用全名。因此,如果您大部分时间都使用全名,那么一个字段实际上会更好。

    【讨论】:

    • (1) OP 显然使用的是 Oracle 而不是 MySQL (|| ', '||) (2) 在单个字段中保存名称是真的很糟糕的建议。拆分比连接复杂得多,您永远无法 100% 确定如何正确拆分。
    【解决方案3】:
    SELECT CONCAT(SUBSTRING_INDEX(PERSON, ' ',-1),', ' ,SUBSTRING_INDEX(PERSON, ' ',1)) FROM LEDGER
    

    【讨论】:

    • OP 显然使用的是 Oracle 而不是 MySQL (|| ', '||)
    【解决方案4】:

    甲骨文解决方案

    select  regexp_replace (person,'(\S+)(\s+\S+)?\s+(\S+)','\3, \1') as persons
    from    ledger
    

    +----------------+
    |    PERSONS     |
    +----------------+
    |  Franklin, Bob |
    |  Smith, Gene   |
    |  Biv, Roy      |
    +----------------+
    

    \s - A whitespace character.
    \S - A non-whitespace character.
    +  - Matches one or more occurrences
    ?  - Matches zero or one occurrence
    

    REGEXP_REPLACE
    Oracle Regular Expression Support

    【讨论】:

      【解决方案5】:

      你可以用这个

      substr(PERSON,INSTR(PERSON,' ', -1) )||', '|| substr(PERSON,1,INSTR(PERSON,' ', -1) )
      

      【讨论】:

        【解决方案6】:

        你可以直接使用下面提到的select语句。

        select substr(PERSON,instr(PERSON,' ',-1))||', '||substr(PERSON,instr(PERSON,' ',1),instr(PERSON,' ',-1)-instr(PERSON,' ',1))||' '||substr(PERSON,0,instr(PERSON,' ',1)) from ledger;
        

        或者将它全部包含在 with 子句中并从另一个看起来简单易用的 select 子句中调用它,如下所示:

        with temp_ledger as (
        select substr(PERSON,instr(PERSON,' ',-1)) as l_name ,substr(PERSON,instr(PERSON,' ',1),instr(PERSON,' ',-1)-instr(PERSON,' ',1)) as m_name, substr(PERSON,0,instr(PERSON,' ',1)) as f_name from ledger )
        
        select l_name||', '||m_name||' '||f_name from temp_ledger;
        

        注意:您还可以使用 3 个以上的词来处理姓名,例如 “Jean Claude van Damme”

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-02-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多