MySQL 最长前缀匹配 100 万条记录与 3000 种可能性

标签 mysql sql match prefix

我有一个包含大约 100 万个电话号码的表格和另一个包含大约 3000 个 ISD 代码(国家/地区代码)的表格。现在我想在最长前缀匹配上将电话号码与所有这些 ISD 代码进行匹配。 在 ISD 表中,我可以有例如:

1     US
1808  US (Hawaii)

如果电话号码现在是 1223244223,它应该返回美国,但如果是 1808322353,它应该返回美国(夏威夷)。 以最佳性能实现这一目标的最佳方法是什么?

这是我目前所拥有的。不幸的是对性能不满意,我想避免使用函数:

DELIMITER $$

CREATE DEFINER=`root`@`localhost` FUNCTION `isd`(telnum varchar(32)) RETURNS int(4)
BEGIN
    RETURN (SELECT if(locate(isd, telnum)=1, (locate(isd, telnum)*length(isd)), 0) as score FROM tbl_ref_isd_v1 having score>0 order by score desc limit 1);
END

此外,我还有这个不同的功能,它似乎更快一些:

DELIMITER $$

CREATE DEFINER=`root`@`localhost` FUNCTION `isd_new`(telnum varchar(32)) RETURNS int(4)
BEGIN
    RETURN (
        select isd 
from test.tbl_ref_isd_v1 
where telnum like CONCAT(isd, '%') 
order by length desc LIMIT 1
    );
END

最佳答案

这是一个执行您想要的操作的查询:

select pn.*, max(ic.code)
from (select pn.*, ic.code, len(ic.code)
      from PhoneNumbers pn join
           ISDCodes ic
           on pn.phonenumber like concat(ic.code, '%')
     ) pni
group by pn.phonenumber;

请注意,对于初始字符串,max() 有效,因为 1808 大于 1,依此类推。

编辑:

ISDCodes(code) 上建立索引。那么以下应该可以正常工作:

select pn.*, coalesce(ic5.code, ic4.code, ic3.code, ic2.code, ic1.code) as code
from PhoneNumbers pn left outer join
     ISDCodes ic1
     on left(pn.phonenumber, 1) = ic1.code left outer join
     ISDCodes ic2
     on left(pn.phonenumber, 2) = ic2.code left outer join
     ISDCodes ic3
     on left(pn.phonenumber, 3) = ic3.code left outer join
     ISDCodes ic4
     on left(pn.phonenumber, 4) = ic4.code left outer join
     ISDCodes ic5
     on left(pn.phonenumber, 5) = ic5.code;

您需要连接到更长的 ic.code

关于MySQL 最长前缀匹配 100 万条记录与 3000 种可能性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22134640/

相关文章:

c# - 如何检查正则表达式组是否相等?

Javascript 正则表达式,确定匹配哪个组

mysql - 禁用特定表的 BinLogging,在哪里执行参数更改

mysql - 选择不同的列

php - SQL 加入收藏夹列表返回错误的名称

sql - 您可以使用 CASE 语句来评估您传递给存储过程的参数吗?

MySQL,索引和 "Lock wait timeout exceeded"

php - 插入具有更高顺序值的新行时,如何更改表中的顺序值?

mysql - 自增Id和key问题(MySQL)

python - 根据另一列匹配部分文本