自动建议机场 - 如何在多个列中订购“最佳匹配”?

时间:2011-01-10 19:03:28

标签: php sql mysql

给出以下表结构:

id  iata  icao  name
 1  ANC   PANC  Anchorage - Ted Stevens International
 2  LHR   EGLL  London - Heathrow
 3  LGW   EGKK  London - Gatwick
 4  MDZ   SAME  Mendoza - Governor Francisco Gabrielli International

以“最佳匹配优先”顺序提取记录的最佳方法是什么,正如您在旅行社网站的自动建议字段中所期望的那样?任何一列中="string"上的匹配优先于任何其他列中LIKE "%string%"上的匹配。在那之后,“名字”的字母顺序可能就是我想要的。

例如,搜索“anc”将返回第1行然后第4行。“lon”将返回3然后是2.

IATA代码始终为3个字符,ICAO始终为4.但是,其中一个或两个都可能为NULL。

虽然我希望我的AJAX能够提交三个字符并从那里过滤Javascript,我不能假设输入将是三个字符 - 非Javascript用户将提交任意长度的字符串。

我在PHP中使用MySQL进行此操作。

3 个答案:

答案 0 :(得分:1)

这是一个难以破解的难题。以下是我过去使用的一些因素,其次是相对权重。

  1. 完全匹配:50(基本上:100%成功)
  2. Levenshtein距离< 2:25(除掉拼写错误 - 相当密集的算法)
  3. 名称开头的部分匹配:15
  4. 在名称的某处部分匹配:10
  5. 完全匹配将基于此得到100分(它匹配所有)。然后我简单地按重量加权排序。

    对于我的数据集(歌曲名称),这产生了非常好的结果。不确定它是如何与你的相媲美的。

    在你的情况下,我会添加一个“如果输入是3个字符,那么如果它匹配IATA则为50分,如果匹配ICAO则为50分,如果它与ICAO匹配”,则添加到列表中。

    如何在SQL中执行此操作:

    SELECT SUM(
        IF(`name` = :Input, 50, 0),
        IF(`iata` = :Input, 50, 0),
        IF(`icao` = :Input, 50, 0),
        IF(`name` LIKE CONCAT('%', :Input, '%'), 25, 0),
        ...
    ) FROM Table;
    

    排序是在PHP中完成的。

    不漂亮或优雅,但它有效。

答案 1 :(得分:1)

这是一个相当简单的方法:

SELECT ID, 1 As Certainty FROM airfields where iata = @searchValue OR icao = @searchValue OR name = @searchValue
UNION
SELECT ID, 2 FROM airfields where iata <> @searchValue AND icao <> @searchValue AND NAME <> @searchValue
AND (iata LIKE '%' + @searchValue + '%" OR icao LIKE '%' + @searchValue + '%" OR name LIKE '%' + @searchValue + '%")
ORDER BY Certainty

因此,完美匹配始终优先。你可能想在那之后收紧订单。

答案 2 :(得分:1)

如果您正在运行MyISAM类型表,请使用全文索引。匹配将为您提供相关性,您可以使用它来订购结果。 http://dev.mysql.com/doc/refman/5.5/en/fulltext-search.html#function_match

请改用Apache Solr或Sphinx。