2

希望一位伟大的思想家可以在这里帮助我。

我有一种情况,我将从提供商那里收到一个国际电话号码,我必须进行数据库查找并找出电话号码所拨打的国家、地区和电话类型。

例如,假设我将收到一个电话号码 +393234567891。我必须在表格中查找电话号码所属的国家/地区。所以我知道“39”是意大利,我在数据库中有一个国家代码,但我必须确定这个号码是固定电话还是手机。为此,我需要电话号码中的更多信息,因此“39”是固定电话,“393”是手机。我需要看到电话号码包含“393”,因此我知道它是一部手机。

我的问题是评估这个的最佳方法是什么?是否会循环遍历电话号码的每个部分,例如首先将前两个电话号码与数据库进行比较,然后是前三个,然后是前四个,直到我返回一个结果?例如,如果我继续这个例子,并将意大利的 '39' 与 db 进行比较,我会返回一堆结果,因为有 '39' 和 '393' 和 '3939' 等等。那么使用整个电话号码来获得电话号码前缀的完全匹配的最佳方法是什么?

我本来想只循环电话号码并将电话号码的数字添加到循环中,直到我只返回一个结果,我只是想确保这是完成此操作的最有效方法。

有什么建议吗?谢谢!

4

4 回答 4

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'
于 2011-04-06T10:05:18.000 回答
0

如果实际电话号码是固定大小的,您可以将其删除。用 sub_strreplace; 例如,数字是 8 位数字:

$code = substr_replace($number,'',-1,8);

$code 现在将只包含代码部分。这样您就可以轻松地计算数字并找出您需要的东西。

于 2011-04-06T09:48:17.853 回答
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
}

我认为这会起作用,但我想我必须查看确切的数据结构才能确定。但是是的,两张桌子绝对是可取的

于 2011-04-06T10:11:06.810 回答
-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 ;
}
于 2011-04-06T10:37:17.047 回答