【问题标题】:The most efficient sql schema for searching names and lastnames搜索姓名和姓氏的最有效的 sql 模式
【发布时间】:2011-09-08 04:20:40
【问题描述】:

我正在我的网站上创建一个成员列表,我想让他们通过名字和姓氏或其中之一来查找彼此。问题是一个用户可以有多个名字,比如名字和昵称,一个人也可以有多个姓氏,他们的婚前姓氏和婚后姓氏。

一旦用户填写了他们的姓名和姓氏,每个用户可能有多个姓名和姓氏,例如,可能有一个人有 3 个姓名和 2 个姓氏 - 姓名:Eleonora、Ela、El 和姓氏:Smith、Brown。

然后,如果有人寻找 Ela Brown、Eleonora Brown、Eleonora Smith 或任何其他组合,他们应该找到这个人。

我的问题是,我应该如何在 sql (mysql) 中设置这一切,以便架构和搜索既高效又快速?不想重新发明轮子,所以我求助于专业人士并在这里提出问题。

谢谢大家

附:我想标准的解决方案是有一个用户表、fname 表、lname 表、带有 userid 和 fnameid 的 userfname 表以及带有 userid 和 lnameid 的 userlname 表,但我不确定这是否是最好的方法。或者不搜索会很快......

【问题讨论】:

    标签: mysql sql schema


    【解决方案1】:

    您需要区分名字和姓氏吗?

    我建议Users 表有UserID
    还有一些UsersNames 表具有UserIDName,一对多的关系。

    如果需要,您还可以在UsersNames 表中添加一个IsLastName 位(或只是一个LastName 列,但恕我直言,该位更好)....
    但是这样一来,您搜索一个表就可以轻松找到用户 ID,而且您不会限制每个用户可以拥有的名称数量。

    编辑: 您也可以轻松获取输入字符串并将其拆分。因此,如果有人输入“John Smith”,您可以通过拆分字符串并在WHERE 子句中使用ORAND 来搜索这两个名称或其中一个名称,具体取决于您的预期功能。

    【讨论】:

    • 我需要能够区分姓名和姓氏。
    • 对,所以您添加一个IsLastName 列或仅添加一个LastName 列,以便您的搜索可以轻松返回您拥有的列。归根结底,它只是一个带有属性的字符串。
    • 在此基础上进行扩展,您可以这样做 SELECT * FROM Users WHERE Users.UserID IN (SELECT UserID FROM UserNames WHERE UserName.Name IN ('John', 'Smith')) ORDER BY (SELECT COUNT(1) FROM UserNames WHERE UserName.Name IN ('John', 'Smith')) DESC 这将使您能够以最有可能的结果排序
    • @Seph 如果你有 exact 匹配项,我想这是真的。
    • 它也适用于全文搜索以进行部分单词匹配,但我的 sql 示例将为您提供匹配名称的优先级列表。也就是说,它会显示“John Smith”,然后是“John Jones”,然后是“Bob Smith”,但它也会返回与“John Smith”相同(或更高)级别的“Smith John”
    【解决方案2】:

    您需要的是文本搜索 - 使用 Lucene。我已经在几个项目中使用了 Lucene,它真的很棒 - 不难使用而且速度快得离谱。

    【讨论】:

      【解决方案3】:

      如果在您的数据模型中,用户可能有多个但数量有限的名称类型,那么最简单的解决方案是为存储名称类型的每个列创建索引。您可以为名字、姓氏、昵称、婚前姓等添加一个字段。此模型比具有一对多名称关联的性能更高。

      您还可以评估应用程序的其余部分是否有一般搜索要求,或者您是否希望搜索更加灵活。在这种情况下,您可以考虑使用后端索引过程,例如使用Lucene 或使用full text search。最初,我会尽可能避免这种情况,因为这肯定会使项目复杂化。

      【讨论】:

      • 我不明白你回复的第一段,你能给我举个例子吗?
      • OP规定名字个数不限
      • 所以,如果我有很多但有界(比如 100 个)名称类型,那么最简单的解决方案是创建 100 个字段?而且这个模型会更高效?
      • 100 个字段太多,无法以这种方式管理,我会转而采用 Matthew PK 指定的方法。我只是提出了这样一个概念,即如果不同名称类型的数量很少,那么创建一个额外的表可能是多余的。
      【解决方案4】:

      上次我做这样的事情时,我将每个名称处理成 NAMES 表中的单个列。所有名字,名字/姓氏/中间名。第二个表包含指向 PERSONS 表中人员记录的链接。

      因此,每个 NAME 字段都链接到一个或多个 PERSONS 记录。如果我搜索“Scott”,我会在 NAMES 表中找到名称 Scott,在 NAMES_TO_PERSONS(/PEOPLE?) 表中找到链接,然后返回该名称的所有记录。即:斯科特·布伦斯、约翰·斯科特、大卫·斯科特·史密斯。

      只需要少量的预处理就可以很好地工作。

      【讨论】:

      • 但是您将无法搜索“John Smith”,因为它也在姓氏中查找 John?
      • @user720943:不,您将能够搜索。在此模型中,您首先将JohnSmith 分开,然后查询表。它会找到任何John Smith 和任何Smith John(将Smith 作为名字或昵称,将John 作为姓氏)。查询会稍微复杂一些,但在某些情况下您会有更大的灵活性。
      • user720943,你是对的。我忘了补充一点,我们存储了每个名称组合。因此,如果名称是 Scott David Bruns,我们存储 Scott/David/Bruns/Scott David/Scott Bruns/David Bruns。这可以根据需要进行调整。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      • 2021-12-16
      • 1970-01-01
      • 2011-08-19
      • 1970-01-01
      • 2012-02-19
      相关资源
      最近更新 更多