希望其中一位伟大的思想能够帮助我。
我的情况是,我将从提供商处收到国际电话号码,我必须进行数据库查询,并找出电话号码正在拨打的国家,地区和电话类型。
例如,假设我将收到一个电话号码+393234567891。我必须在表格中查找电话号码所属的国家/地区。所以我知道'39'是意大利,我把它作为数据库中的国家代码,但我必须确定这个数字是固定电话还是手机。为此我需要更多的电话号码信息,因此'39'是固定电话,'393'是手机。我需要看到电话号码包含'393',因此我知道它是一部手机。
我的问题是评估此问题的最佳方法是什么?是不是要遍历电话号码的每个部分,比如首先将前两个电话号码与数据库进行比较,然后是前三个电话号码,然后是前四个电话号码,直到我用一个结果回来?例如,如果我继续这个例子,并将意大利语的“39”与数据库进行比较,我将返回一堆结果,因为有'39'和'393'和'3939'等等。那么使用整个电话号码获得电话号码前缀的完全匹配的最佳方法是什么?
我本以为只是循环通过电话号码并在循环中添加一个电话号码,直到我回来只有一个结果,我只是想确保这是实现这一目标的最有效方法。
有什么建议吗?谢谢!
答案 0 :(得分:2)
我假设你有一个像这样的表:
prefix (id, number)
使用以下数据:
1, '39'
2, '393'
3, '33'
4, '331'
您可以使用反向LIKE 获得最长匹配:
SELECT id
FROM prefix
WHERE "393234567891" LIKE CONCAT(number, "%")
ORDER BY LENGTH(number)
LIMIT 1;
我还没有对它进行测试,但假设您的最短前缀是2个字符,您可能会得到一些改进(这只会检查以39
开头的前缀,即所有前缀的1%):
SELECT id
FROM prefix
WHERE "393234567891" LIKE CONCAT(number, "%")
AND number LIKE "39%"
ORDER BY LENGTH(number)
LIMIT 1;
然后你可以有一个不同的表,其中包含附加到该前缀的信息:
prefixinfo (id, prefix_id, type, data)
使用以下数据:
1, 1, 'country', 'Italy'
2, 2, 'country', 'Italy'
3, 2, 'type', 'Landline'
4, 3, 'country', 'France'
5, 4, 'country', 'France'
6, 4, 'city', 'Paris'
答案 1 :(得分:0)
如果实际电话号码是固定大小,您可以将其删除。与sub_strreplace;例如数字长度为8位数:
$code = substr_replace($number,'',-1,8);
$ code现在只包含代码部分。这样您就可以轻松计算数字并找出所需内容。
答案 2 :(得分:0)
在393中表示移动设备的最后3个,对于每个国家/地区都是一样的吗?
理想的情况是为国家/地区设置一个表格,然后是另一个带有相关前缀的表格
Countries table Subsearch Table
countryMatch: 39 substrMatch: 3 // for 393
countryName: "Italy" substrCountry: 39
substrMeaning: "cell"
...................
substrMatch: 5 // 395
substrCountry: 39
substrMeaning: "something else"
这样一旦您确定了国家/地区,就可以限制其余搜索内容以进一步限制,例如: 393,3939。
我认为你提出的方法是合理的,一点一点地循环,直到找到使用SQL查询的匹配。因此,通过弹出前两位数(39)来查找国家/地区代码,如果找到则查询子搜索表以获取结果。通过将这些结果循环添加到国家/地区代码并查看是否获得匹配
$subsearchArr = array("3" => "cell","5" => "something else") # from the database
$match = false;
$country = 39;
foreach($subsearchArr as $key => $value)
{
# append $key to $country e.g. 393, 395
# if this is a match to the string
# set match to true and do your logic
}
if($match == false) # no match so landline
{
# logic here if landline
}
我认为这样可行,但我想我必须看到确切的数据结构。但是,两张桌子绝对是可取的
答案 3 :(得分:-1)
使用简单的数组循环在PHP中进行比较可能会更好,即使你在Mysql中有数据也是如此。从数据库(和缓存)构建一个预期国家代码的PHP数组和每个国家/地区内已知的唯一前缀,以区分移动,固定电话,区域等。
对于您拥有的每个国家/地区代码,请查看输入的电话号码是否以该代码开头。找到国家/地区后,请从电话号码中删除国家/地区代码,然后根据该国家/地区的已知移动电话号码前缀列表测试剩余电话号码。如果找到,它是移动的。如果没有找到,那就是固定电话。
例如,在希腊,国家代码为30,之后所有手机都以69开头。但是,如果您正在通过移动电话号码前缀与区号(例如美国和加拿大)无法区分的国家/地区进行实际操作,那么您运气不佳。
function checkMSISDN($msisdn) {
$countries = array(
'gr' => array(
'countryPrefix' => '30',
'mobilePrefix' => '3069',
'length' => 12,
),
'it' => array(
'countryPrefix' => '39',
'mobilePrefix' => '393',
'length' => 12,
),
) ;
foreach ($countries as $countryName => $countryRules) {
$msisdnCurrent = $msisdn ;
$countryPrefix = $countryRules['countryPrefix'] ;
$fullPrefix = $countryRules['mobilePrefix'] ;
//remove leading + if any
if (substr($msisdnCurrent, 0, 1) == '+') {
$msisdnCurrent = substr($msisdnCurrent, 1) ;
}
//remove leading 00 if any
if (substr($msisdnCurrent, 0, 2) == '00') {
$msisdnCurrent = substr($msisdnCurrent, 2) ;
}
$msisdnLength = strlen($msisdnCurrent) ;
if ($msisdnLength != $countryRules['length']) {
//sanity check, not this country
continue ;
}
if (substr($msisdnCurrent, 0, strlen($countryPrefix)) != $countryPrefix) {
//not this country
continue ;
}
if (substr($msisdnCurrent, 0, strlen($fullPrefix)) != $fullPrefix) {
//not mobile
return "isLandline" ;
}
else {
//mobile
return "isMobile" ;
}
}
return false ;
}