我的桌子上有大约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
答案 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
。