查询出列表数据后通过fid递归进行排列

解决方案 »

  1.   

    典型的数据结构问题,使用PHP中的数组表示树形结构,然后处理每一行读取的数据
    进行树的插入操作channels['xxx'] = array[]; ... !当然你可以order by fid asc这样处理起来可以方便一点!
    大致的思路,不一定对!
      

  2.   

    查询出列表数据后通过fid递归进行排列。
    我就是不想递归才这么设计的啊?请问大家有什么办不递归吗?
      

  3.   

    $records = db_get_all( 'Select * From XXXX Where 1 Order by channelPath' );
    foreach( $records as $record )
    {
      $depth = count( explode(',',$record['channelPath']) );
      echo str_repeat('&nbsp;',$depth).$record['channelName'].'<br />';
    }
      

  4.   

    himan2002  果然是高人
    不错,
      

  5.   

    楼上的说:channlePath字段完全是多余???????????
    如果不用channlePath您能一次性查询出来像4楼的朋友那样的结果吗?
      

  6.   

    'Select * From XXXX Where 1' 就一次查出所有的数据
    根据fid就可以得到父数据,所以没必要channlePath字段,你使用channlePath字段还要去切割字符串“一次查出所有的数据”的方法,对于数据量小没问题,如果数据量大就有问题了。对于大数据量还是使用递归查询的方式
      

  7.   

    还有就是用channlePath还有一个缺点:
    如下图:我是先添加:1,0
              再添加:2,0
              后添加:11,0
    使用:select * from mm order  by id asc;
    查询出来的结果:却不太尽如意,2,0跑到了最后,当然这对某一个类别的子类没有什么影响,但影响了根类
    顺序,如果遇到像11,22,55,66...这样的和1,2,5,6排序比较的话,就会把整个类及其子类搞的顺序不对:
    应当如何解决啊?
      

  8.   

    <?php
    echo count( explode(',',"0,2,5,7,8,")); //输出6
    echo "<hr>";
    echo count( explode(',',"0,2,5,7,8,9,")); //输出7
    ?>
    不知道12楼所谓的产生退格是什么意思啊?
      

  9.   

    channlePath字段副作用是相当大的比如我以后在“水果”前添个父类“果实”也就是
    12 0“果实”
    有channlePath字段你想想要多少步骤?苹果、香蕉所以涉及“水果”的都要改不用的话只要改
    1 12 “水果”中的12
    想到使用channlePath字段的人我估计是惧怕使用递归的人想的一个最失败的方法
      

  10.   

    楼主发短消息要求解释我的回复,其实自己做一下测试就可以了$ar = array(
    array('别克', '0,2,5,7,8,'),
    array('中国别克', '0,2,5,7,8,9,'),
    );
    foreach( $ar as $record ) { 
      $depth = count( explode(',',$record[1]) ); 
      echo str_repeat('_',$depth).$record[0].' <br />'; 
    }
    ______别克 
    _______中国别克 对于13楼的问题
    由于channlePath保存的是串,而不是字符类型的数字.对于后者可指定按自然数排序得到正确的序列
    而对于前者则只能按字符串的排序规则进行了
    若想得到正确结果,又不想放弃本方案,则必须重构channlePath:指定每个级别的宽度,并设有前导的0
    2,0 -> 002,000
    11,0 -> 011,000
    很显然,这已经不是"无限"分类了
      

  11.   

    HOHO,这种结构不是很好,如果要将一个分类,转到另一个分类下,程序处理很麻烦
      

  12.   

    这样明显有个好处.消除了递归
    order by channlePath再用 substr_count($channlePath, ",")来写树形结构.不是很方便吗
      

  13.   

    这样明显有个好处.消除了递归
    order by channlePath再用 substr_count($channlePath, ",")来写树形结构.不是很方便吗
      

  14.   

    channlePath存在基本无意义,没有他实现递归很容易,有好是麻烦老大的话已很明白了以前看过一些树结构,如果要实现前面的线图,实现起来要复杂的多(2-3倍)特别是在浏览器的DOM中,否则的CSDN的梅花树就基本没有技术含量了不知道CSDN的梅花树是如何做的,没太细看,它是如果自动判断在其前面的每一级都加图片?
      

  15.   

    上面的channlePath并非用作显示排序或者判断父节点。这列冗余数据是特殊需求所需要的。如果要用它来排序,需要对其做处理(比如格式化为10位)楼主可以这样想:
    如果数据表中存的数据和整个树形菜单完全展开的排序,完全一样,那么你取数据的时候还需要递归么?不需要,直接按照主键顺序读出数据,根据fid判断深度,一切ok了不是么?(当然了你可以加入一些冗余数据以简化深度判断)+----+-----+----------+
    | id | fid | name     |
    +----+-----+----------+
    |  1 |   0 | 水果     | 
    |  2 |   1 | 苹果     | 
    |  3 |   1 | 香蕉     | 
    |  4 |   0 | 车       | 
    |  5 |   4 | 火车     | 
    |  6 |   5 | 中国火车 | 
    |  7 |   5 | 美国火车 | 
    |  8 |   4 | 汽车     | 
    |  9 |   8 | 小汽车   | 
    | 10 |   9 | 别克     | 
    | 11 |  10 | 中国别克 | 
    +----+-----+----------+
    目的其实就是加快读取,生成速度。那么我们就牺牲下添加,修改,删除的速度来达到它,未尝不可吧?
    用个最笨的方法,建2张表,一张递归的,后台修改用,一张显示用的,如上,每次修改都重新生成后一张表。可以吧?怎么说也比每次显示都递归强的多!(废话说多了,意思就是考虑这个问题是要分清主次,就算这种最笨的办法都比显示的时候递归调用强)剩下的,好办了,怎么样用一张表完成以上要求(快速显示,添加,修改,删除)。
    接下来只要适当的在这张最简单的表中适当加入冗余字段就可以了,比如channlePath,甚至再加一列整数列,存储channlePath排序的顺序号(加快读取速度,索引为4字节,bt了点,实际使用中没多大用,哪有那么多数据)。
      

  16.   

    给你个比较实用的id      int   主键
    fid     int   父节点id
    orderby int   顺序编号(同一父节点下的排序顺序,排序用,可以任意指定一个整数。)
    name    char  节点名称
    path    char  节点路径,格式和楼主所说差不多,但需要把id格式化,如0000000001,0000000022,字段长度根据实际需要确定
    这个基本上就能满足你的需要了。
    排序方法: order by path,orderby
      

  17.   

    以下是正确答案,id          int    主键
    fid         int    父节点id
    order_num   int    同一fid下的顺序编号,相同fid,order_num不可重复
    order_by    int    最终的排序字段,非必要。通过sql生成
    name        char   节点名称
    order_str   char   类似channlePath,但存的是order_num
    mysql> select * from yh_s;
    +----+-----+-----------+----------+----------+--------------+
    | id | fid | order_num | order_by | name     | order_str    |
    +----+-----+-----------+----------+----------+--------------+
    |  1 |   0 |         2 |        9 | 水果     | 0,2,         | 
    |  2 |   1 |         2 |       11 | 苹果     | 0,2,2,       | 
    |  3 |   1 |         1 |       10 | 香蕉     | 0,2,1,       | 
    |  4 |   0 |         1 |        1 | 车       | 0,1,         | 
    |  5 |   4 |         2 |        6 | 火车     | 0,1,2,       | 
    |  6 |   5 |         2 |        8 | 中国火车 | 0,1,2,2,     | 
    |  7 |   5 |         1 |        7 | 美国火车 | 0,1,2,1,     | 
    |  8 |   4 |         1 |        2 | 汽车     | 0,1,1,       | 
    |  9 |   8 |         1 |        3 | 小汽车   | 0,1,1,1,     | 
    | 10 |   9 |         1 |        4 | 别克     | 0,1,1,1,1,   | 
    | 11 |  10 |         1 |        5 | 中国别克 | 0,1,1,1,1,1, | 
    +----+-----+-----------+----------+----------+--------------+
    11 rows in set (0.00 sec)
     
    mysql> select * from yh_s order by order_by;
    +----+-----+-----------+----------+----------+--------------+
    | id | fid | order_num | order_by | name     | order_str    |
    +----+-----+-----------+----------+----------+--------------+
    |  4 |   0 |         1 |        1 | 车       | 0,1,         | 
    |  8 |   4 |         1 |        2 | 汽车     | 0,1,1,       | 
    |  9 |   8 |         1 |        3 | 小汽车   | 0,1,1,1,     | 
    | 10 |   9 |         1 |        4 | 别克     | 0,1,1,1,1,   | 
    | 11 |  10 |         1 |        5 | 中国别克 | 0,1,1,1,1,1, | 
    |  5 |   4 |         2 |        6 | 火车     | 0,1,2,       | 
    |  7 |   5 |         1 |        7 | 美国火车 | 0,1,2,1,     | 
    |  6 |   5 |         2 |        8 | 中国火车 | 0,1,2,2,     | 
    |  1 |   0 |         2 |        9 | 水果     | 0,2,         | 
    |  3 |   1 |         1 |       10 | 香蕉     | 0,2,1,       | 
    |  2 |   1 |         2 |       11 | 苹果     | 0,2,2,       | 
    +----+-----+-----------+----------+----------+--------------+
    11 rows in set (0.00 sec)