求一个高效的算法,大家各抒己见

项目里的分类设计:
12230000,一共八位,每两位表示一个分类层级。
例如:
12000000表示“家装建材”
12230000表示“家装建材”->“瓷砖地板”
12230100表示“家装建材”->“瓷砖地板”->“防水地板”
设计的优点:
对于获取某个分类(瓷砖地板)下面的子分类直接:select * from table where id > 12230000 and id <= 12239900,然后从这个结果里面踢掉最后两位非0的记录。

这样设计随即的麻烦来了,我们怎么求出:12239900?对于计算一个二级分类下的子类这个最大值是12239900,但对于计算一级分类下的子类这个最大值就变成:12990000,同样计算三级分类子类这个最大值为:12239999。

怎么可以很优雅地计算这个最大值?现在的做法很笨:字符串截取,连接然后再str_pad。

评论 (3)链接2012-02-29 
  • 0 支持
    你这个要算的最大值是某个分类下的子类的最大值吧? – 张玉海 2012-02-29
  • 0 支持
    一串数字,想不通为啥要用Str的方式,数字求余,求商都行的。 – Mosence 2012-06-21
  • 0 支持
    其实挺好的啊……这方法……没啥不高效的。和你后面跟着的那个Select的消耗一比,你在乎前面是用字符串还是用数值运算就傻得可爱了。 – 灵剑2012 2012-09-18

通过@zhupp 提供的思路更改如下:

  
$num = 12011000;    
$level = 0;
while(($num % 100) === 0) {
$level++;
$num /= 100;
}
echo $level;
//an=a1+(n-1)*d
//a1 = 2;
//a2 = 2 + (2-1)*2 = 4;
//a3 = 2 + (3-2)*2 = 6;
//max = num + pow(10, an)
//$sql = select * from table where id > num and id < max
soooldier
编辑于 2012-03-11
该答案已被锁定,无法对其进行评论,编辑及投票。
()
评论 (0)链接 • 2012-02-29

每个层级的位数可以确定那么 可以这样设计:
增加pid字段, 每条记录的 的 pid 为 上级的pid
增加level字段,为当前分类等级
举例:
id       name     pid level
12     家装建材     0 1
13     瓷砖地板     12 2
14     防水地板     13 3

如果查找 id为 13 下边的之类,pid=13 level=3

Codefor
Codefor
3
编辑于 2013-10-31
该答案已被锁定,无法对其进行评论,编辑及投票。
()
评论 (2)链接 • 2012-02-29
  • 0 支持
    做like操作吗?恩。。这个方法也可行,但是纠结的是现在数据结构没法变了,哎。 – soooldier 2012-02-29
  • 0 支持
    不错,like 和截串都可以,pid 建立索引。 like 1213% 这样也能利用到索引。
    数据可以写一个脚本跑一遍。
    – 冯义军 2012-02-29

你这样设计有个问题,那就是三级分类下的物品不能超过99个,我估计挡不住吧?
如果非要这样,分析如下:
对于计算一级分类下的子类这个最大值小于12000000+1000000;
对于计算二级分类下的子类这个最大值小于12230000+10000;
对于计算三级分类下的子类这个最大值小于12239900+100。
所以有这么个逻辑关系:
一级分类下的+1000000
二级分类下的+10000
三级分类下的+100

该答案已被锁定,无法对其进行评论,编辑及投票。
()
评论 (1)链接 • 2012-02-29
  • 0 支持
    恩,你说的很对,分类不能超过99个。你说的这个比我的方法要好!顶一个! – soooldier 2012-02-29

给你写了一个简单的方法,不用截字符串

  
function getMax($start){
$decimal = rtrim($start, 0);
$remainder = $start/$decimal;
$cop = ($remainder * 99)/100;
return $start + $cop;
}

$start =122300000000;
echo getMax($start);
该答案已被锁定,无法对其进行评论,编辑及投票。
()
评论 (1)链接 • 2012-02-29
  • 0 支持
    多谢兄弟回答 ,我想得到的完美答案一定是不能把这个数当成是字符串操作,虽然php是弱类型。 – soooldier 2012-02-29
  
function getMaxId($id){
//最大支持9位数
if($id<0 || $id>999999999) return -1;

$mod = 100;
$n=99;
if($id) while(!($n=($id%$mod))) $mod*=100;
return $id-$n + $mod*.99;
}
function getMinId($id){
//最大支持9位数
if($id<0 || $id>999999999) return -1;

$mod = 100;
$n=0;
if($id) while(!($n=($id%$mod))) $mod*=100;
return $id-$n;
}
$id = 12345678;
echo 'Min:', getMinId($id), "\r\n";
echo 'Max:', getMaxId($id);
/*
输出:
Min:12345600
Max:12345699
*/

这样子够优雅了吗?

该答案已被锁定,无法对其进行评论,编辑及投票。
()
评论 (0)链接 • 2012-03-03
  
function getMaxChild($pid){
//$pid=12206100;
$str='';
for($i=1;$i<=4;$i++){
$test=substr($pid,0,2);
$pid=substr($pid,2,strlen($pid));

if($test=="00"){
return $str.'99'.$pid;break;
}elseif($i==4){
return false;
}else{
$str.=$test;
}
}
}

echo getMaxChild('12200000');
小飞
小飞
6832
编辑于 2012-03-02
该答案已被锁定,无法对其进行评论,编辑及投票。
()
评论 (3)链接 • 2012-02-29
  • 0 支持
    哈哈,我现在就是这么做的,但是感觉特别别扭,明明是一个数字却是把它当成字符串来用了~ – soooldier 2012-02-29
  • 0 支持
    我去,什么时候编辑问题了,0是个好办法哈,+1 – 张玉海 2012-02-29
  • 0 支持
    兄弟们每提一个建设性的意见都会编辑一下问题 哈哈哈~ – soooldier 2012-02-29
德问是一个专业的编程问答社区,请 登录注册 后再提交答案