如何显示和正确缩进单个节点的树结构?

时间:2012-10-03 10:17:53

标签: php

DB结构如下:

    cat_ID| cat_name    | cat_nicename  | lft | rgt 
    _________________________________________________
    287   | Wallpapers  |  wallpapers   | 61  | 62
    1656  | Gadget      |  gadget       | 63  | 64
    1958  | Sms         |  sms          | 65  | 66
    2901  | fun         |  fun          | 67  | 68
    4419  | Joke        |  joke         | 69  | 70
    4775  | health      |  health       | 71  | 72
    5098  | Mobile      |  mobile       | 73  | 90
    5100  | TV          |  tv           | 91  | 92
    5101  | Main        |  main         | 93  | 94
    5102  | Nokia       |  nokia        | 76  | 83
    5103  | Samsung     |  samsung      | 84  | 87
    5104  | Micromax    |  micromax     | 88  | 89
    5105  | Nokia Sub 1 |  nokiasub1    | 77  | 78
    5106  | Nokia Sub 2 |  nokiasub2    | 79  | 82
    5107  | Nokia Sub 3 |  nokiasub3    | 80  | 81
    5109  | Galaxy      |  galaxy       | 85  | 86

我用来获取One类及其所有子类的Folloing查询:

$sql = "SELECT n.cat_ID,n.cat_name,n.cat_nicename, (COUNT(*)-1)
 AS depth FROM " .TBL_CATEGORIES. " AS n, " .TBL_CATEGORIES. " AS p
  WHERE p.cat_nicename='mobile'
 AND n.lft BETWEEN p.lft AND p.rgt
 GROUP BY n.lft ORDER BY n.lft;";

$result = mysql_query($sql);

$tree = array();
while ($row = mysql_fetch_assoc($result)) {
  $tree[] = $row;
}

function _tab($depth) {
    $tabs = '';
    while ($depth-- > 0) $tabs .= '    ';
    return $tabs;
}

// bootstrap loop
$result = '';
while (!empty($tree)) {
    $currNode = array_shift($tree);
    $result .= _tab($currNode['depth']) . $currNode['cat_name'] . $currNode['depth'].'<br />';
}

print $result;

如果我不使用p.cat_nicename='mobile',通过上面的代码,树结构显示完美,但如果我想使用p.cat_nicename='mobile'只检索一个节点我得到的所有深度都是{{1因此它不会放置任何'0'并在&nbsp;下显示平面树..如果我只查询'mobile'它应显示为:

"mobile"

所以我的问题是:

  1. 如何显示特定节点的树?
  2. 如何仅显示所有根类别?通过使用单个SQL查询,没有孩子没有子?

1 个答案:

答案 0 :(得分:0)

  1. 查看表结构和查询后,我不这么认为 有一种方法可以在没有的情况下选择特定节点的树 额外的子查询(我可能错了,但这是我唯一的方法 可以在测试时使其工作)。要做到这一点,我建议 将子查询添加到FROM子句中,就像您正在选择一样 从第三张桌子。然后,在您的帐户中添加额外的BETWEEN条件 WHERE条款来测试它。

    这样的事情:

    SELECT
        n.cat_ID, n.cat_name, n.cat_nicename, COUNT(*)-1 AS depth
    FROM
        categories AS n,
        categories AS p,
        (SELECT lft, rgt FROM categories WHERE cat_nicename = 'mobile') AS q
    WHERE
        n.lft BETWEEN p.lft AND p.rgt
        AND p.lft BETWEEN q.lft AND q.rgt
    GROUP BY n.lft
    ORDER BY n.lft;
    

    使用这个,你需要添加所有逻辑处理“哪个” 您希望在子查询中获取树的节点。前两个 表格(np)是正常选择的。这是必需的 获得正确的depth值。 然后,它会比较pq - 但是q已经有限了。所以,一旦你有了正确的depth 然后将值限制为您想要的类别。

  2. 仅显示所有根类别要容易得多。用你的 查询,“根类别”的定义是具有depth = 0的定义。如果您使用MySQL的HAVING子句,则可以轻松检查它 与HAVING depth = 0。请尝试以下方法:

    SELECT
        n.cat_ID, n.cat_name, n.cat_nicename, COUNT(*)-1 AS depth
    FROM
        categories AS n,
        categories AS p
    WHERE
        n.lft BETWEEN p.lft AND p.rgt
    GROUP BY n.lft
    HAVING depth = 0
    ORDER BY n.lft;