这几天一直在做一个需求,要求找出数据库相连的电话号码,相连的号码要求可以是前4位或前3位,可由参数控制的。如下所示:
要求找出4位4连号,输入特征号码为:1256 ;
则应该找出以下号码:+++++++ 代表手机号码中的任意前7位
+++++++1253,+++++++1254,+++++++1255,+++++++1256,+++++++1257,+++++++1258,+++++++1259
数据库为oracle,想了很久都没想到在SQL语句下功夫的方法,据说同事想到了,但经测试没有成功,待想到了数据库方法再贴.
下面写出我在PHP代码中处理的方法:
假设现在已经生成了一个二维数组,接下来我们要对这个数组中的数据进行处理,以得到要求的数据。
先将代码贴下来吧,回家理下思路
/*
* add by 20071030 yangxs 添加对家庭连号的查询
* @notes 本函数可用于对一二维数组中的数据筛选,如:一组号码尾部的几位与一个特征字符串比较,
并得到在这组号码中与特征字符串前后(+/-1的号码,可进位,可控制是否有重号)相同的号码。
例:$arrSrc = array(0 => array('number') => '13028101004'),
1 => array('number') => '13928101000'),
2 => array('number') => '13228101001'),
3 => array('number') => '13028101003'),
4 => array('number') => '13228101002'),
5 => array('number') => '13028100997'),
6 => array('number') => '13328100998'),
7 => array('number') => '13028100999'),
8 => array('number') => '13128101002'),
9 => array('number') => '13628101002'),
10 => array('number') => '15228100586'),
11 => array('number') => '13028101996'),
12 => array('number') => '15688899999'),
13 => array('number') => '15105021006'),
14 => array('number') => '15105021007'),
15 => array('number') => '15105021009'),
);
$t_character = '998';
$repeat = true;
$intLinkNum = 8;
则我们要得到的数据应该是:
$arrSrc = array(0 => array('number') => '13028101996 '),
1 => array('number') => '13028100997 '),
2 => array('number') => '13328100998 '),
3 => array('number') => '13028100999 '),
4 => array('number') => '13928101000'),
5 => array('number') => '13228101001'),
6 => array('number') => '13228101002'),
7 => array('number') => '13128101002'),
8 => array('number') => '13628101002'),
9 => array('number') => '13028101003'),
10 => array('number') => '13028101004')
);
也就是在998前后的数据,且相邻的数据之差应该等于1,如果中间的号码没有找到,则不再向那个方向继续查找
如下程序
* @param object $conn 数据库连接对象
* @param int $intLinkNum 要找到的号码数量
* @param string $t_character 特征字符串
* @param array $arrSrc 源数组
* @param boolea $repeat = true 是否可以包含重复的号码
* @return array 成功则返回一个满足家庭连号条件的数组,失败则返回一个带有错误提示的数组
*
*/
function
get_homelink_number(
$arrSrc
,
$t_character
,
$intLinkNum
=
0
,
$repeat
=
true
)
{
$arrResult
=
array
();
//
最终满足条件的数组,如果没有则为出错信息如:array(0,'参数传递错误!');
$arrMySrc
=
array
();
//
将源数组处理后的数组,其中包含一个用于排序的元素sortval
$arrChar
=
array
();
//
特征字串数组,如传入为1258,则该数组内容为array(1256,1257,1258,1259) 等
$strHaveChar
=
''
;
//
将已经满足基本条件的号码特征字符记录
$ifFound
=
false
;
//
是否能找到尾部与特征字符串相同的数据
$intCharLen
=
strlen
(
$t_character
);
//
首先根据特征字符串的长度来得到要比较的尾数长度
//检测传入参数
if
(
empty
(
$t_character
)
||
count
(
$arrSrc
)
<=
0
)
{
$arrResult
=
array
(
-
1
,
'
参数传递错误!
'
);
return
$arrResult
;
}
//
构造满足特征的字串数组,如:由998构造的数组为:array(998,999,997,1000,996,1001,995,1002,994,1003,993,1004,992,1005,991,1006,990)
$arrChar
[
0
]
=
$t_character
;
for
(
$i
=
1
;
$i
<=
$intLinkNum
;
$i
++
)
{
//
向前加1 pow(10,$intCharLen)可以得到特征字符串进位的整数,如999+1 = 1000(10的3次方); 9999+1 = 10000(10的4次方)
if
((
$t_character
+
$i
)
-
pow
(
10
,
$intCharLen
)
>=
0
)
{
//
进位
$arrChar
[]
=
substr
(
'
0000
'
.
(
$t_character
+
$i
)
,-
(
$intCharLen
+
1
));
//
进位时向前多取一位
}
else
{
$arrChar
[]
=
substr
(
'
0000
'
.
(
$t_character
+
$i
)
,-
$intCharLen
);
}
//
向后减1
if
((
$t_character
-
$i
)
>=
0
)
{
//
只包含大于0的情况,如果小于0则暂时不处理
$arrChar
[]
=
substr
(
'
0000
'
.
(
$t_character
-
$i
)
,-
$intCharLen
);
}
}
//
重新构造满足基本条件的数组,即在 $arrSrc.[$i].number 的最尾的几位在特征字串数组里时,将$arrSrc.[$i]保存的新的数组里,并将当前元素的特征字符串保存,供后面排序使用
foreach
(
$arrSrc
as
$arr
)
{
if
(
count
(
$arr
)
>
0
)
{
if
((
substr
(
$arr
[
'
number
'
]
,-
(
$intCharLen
+
1
))
-
pow
(
10
,
$intCharLen
))
<=
$intLinkNum
&&
(
substr
(
$arr
[
'
number
'
]
,-
(
$intCharLen
+
1
))
-
pow
(
10
,
$intCharLen
))
>=
0
)
{
//
取得当前号码的尾部字符串,如果当前号码的尾部 $intCharLen + 1 位 - 特征字符串进位的整数 >=0 且 <= $intLinkNum 时,表示该号码是特征字符串的进位号码
$tailStr
=
substr
(
$arr
[
'
number
'
]
,-
(
$intCharLen
+
1
));
}
elseif
((
substr
(
$arr
[
'
number
'
]
,-
(
$intCharLen
+
1
))
-
pow
(
10
,
$intCharLen
))
<
0
)
{
//
取得当前号码的尾部字符串,如果当前号码的尾部 $intCharLen + 1 位 - 特征字符串进位的整数 < 0 时,表示该号码是特征字符串的没有进位的号码
$tailStr
=
substr
(
$arr
[
'
number
'
]
,-
(
$intCharLen
));
}
//
查看当前号码的尾部字符串是否在特征的字串数组,如果在则写入新的数组中
if
((
count
(
$arrChar
)
>
0
&&
in_array
(
$tailStr
,
$arrChar
)))
{
//
查看当前号码的尾部字符串是否等于传入的特征字符串,等于则表示在源数组中能找到尾部与特征字符串相同的数据
if
(
$tailStr
==
$t_character
)
$ifFound
=
true
;
$arr
[
'
sortval
'
]
=
$tailStr
;
//
写一个可用于排序的元素
$arrMySrc
[]
=
$arr
;
}
}
}
unset
(
$arrChar
,
$arrSrc
);
if
(
$ifFound
==
false
)
{
$arrResult
=
array
(
-
1
,
'
没有找到匹配的号码信息!
'
);
return
$arrResult
;
}
//
排序
usort
(
$arrMySrc
,
'
sort_char_query
'
);
$strHaveChar
=
''
;
//
检查是否为连续号码
$k
=
0
;
for
(
$i
=
0
,
$h
=
0
,
$j
=
count
(
$arrMySrc
);
$i
<
$j
;
$i
++
)
{
if
(
$i
==
0
)
{
$strHaveChar
=
$arrMySrc
[
$i
][
'
sortval
'
];
$arrResult
[
$h
++
]
=
$arrMySrc
[
$i
];
$k
=
1
;
continue
;
}
/*
if(count($arrResult) == $intLinkNum)
{
break;
}
*/
if
(
$i
>=
1
&&
$strHaveChar
!=
$arrMySrc
[
$i
][
'
sortval
'
]
&&
$strHaveChar
+
1
!=
$arrMySrc
[
$i
][
'
sortval
'
])
{
//
$arrResult = array();
$strHaveChar
=
$arrMySrc
[
$i
][
'
sortval
'
];
//
$k = 1;
}
elseif
(
$repeat
&&
$strHaveChar
==
$arrMySrc
[
$i
][
'
sortval
'
])
//
是否可以重复
{
$arrResult
[
$h
++
]
=
$arrMySrc
[
$i
];
}
elseif
(
$i
>
0
&&
$strHaveChar
!=
$arrMySrc
[
$i
][
'
sortval
'
])
{
$strHaveChar
=
$arrMySrc
[
$i
][
'
sortval
'
];
$arrResult
[
$h
++
]
=
$arrMySrc
[
$i
];
$k
=
$k
+
1
;
}
}
if
(
$k
<
$intLinkNum
)
{
$arrResult
=
array
(
-
1
,
'
没有找到匹配的号码信息!
'
);
}
return
$arrResult
;
}
/*
* add by 20071030 yangxs 自定义二维数组排序函数
* @param array $arr1 前一数组元素
* @param array $arr2 当前数组元素
* @return int 返回是否要交换当前记录与前一记录
*
*/
function
sort_char_query(
$arr1
,
$arr2
)
{
if
(
$arr1
[
'
sortval
'
]
==
$arr2
[
'
sortval
'
])
return
0
;
return
(
$arr1
[
'
sortval
'
]
<
$arr2
[
'
sortval
'
] )
?
-
1
:
1
;
}
注释较多,主要是自己以后想用时方便,哈哈,希望各位看官在发现BUG或有什么新想法时不惜告诉我,我的
QQ:75323501