1

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

我用来获取一个类别及其所有子类别的以下查询:

$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'我得到的所有深度来检索一个节点,'0'因此它不会放置任何&nbsp;并在下面显示扁平树'mobile'..如果我查询只是"mobile"它应该显示如下:

Mobile
    Nokia
        Nokia Sub 1
        Nokia Sub 2
            Nokia Sub 3
    Samsung
        Galaxy
    Micromax

所以我的问题是:

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

1 回答 1

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;
    
于 2012-10-03T13:19:36.507 回答