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

时间:2014-03-02 22:40:18

标签: 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

1 个答案:

答案 0 :(得分:1)

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

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,依此类推。

我应该补充一下。这可以完成工作。它不一定是性能最高的,但这取决于很多因素,StackOverflow可能不是这个问题的最佳位置。

编辑:

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

相关问题