2

我使用具有 lft 和 rgt 值的嵌套集具有以下树结构。

node
    node
        node
    node
        node (selected)
        node
node
node
    node

我想建立一个导航,以便树被展开,只到所选节点的路径,并且不相关的节点被折叠/隐藏。

使用上述方法,树将输出如下:

node
    node
    node
        node (selected)
        node
node
node

这可能使用 php/mysql 吗?如果有任何 sql 专家可以帮助构建查询,我将不胜感激。?

我不介意每个级别是否需要额外的查询,它可能最多只有 4 或 5 级深度......

节点表概述:

--
-- Table structure for table `exp_node_tree_1`
--

CREATE TABLE `exp_node_tree_1` (
  `node_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  `lft` mediumint(8) unsigned DEFAULT NULL,
  `rgt` mediumint(8) unsigned DEFAULT NULL,
  `moved` tinyint(1) NOT NULL,
  `label` varchar(255) DEFAULT NULL,
  `entry_id` int(10) DEFAULT NULL,
  `template_path` varchar(255) DEFAULT NULL,
  `custom_url` varchar(250) DEFAULT NULL,
  `extra` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`node_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=18 ;

--
-- Dumping data for table `exp_node_tree_1`
--

INSERT INTO `exp_node_tree_1` VALUES(1, 1, 12, 0, 'Home', 1, '0', '/', '');
INSERT INTO `exp_node_tree_1` VALUES(5, 10, 11, 0, 'About Us', 2, '4', '', '');
INSERT INTO `exp_node_tree_1` VALUES(6, 6, 9, 0, 'Team', 3, '5', '', '');
INSERT INTO `exp_node_tree_1` VALUES(7, 3, 4, 0, 'Contact Us', 4, '4', '', '');
INSERT INTO `exp_node_tree_1` VALUES(8, 7, 8, 0, 'Awards', 5, '5', '', '');
INSERT INTO `exp_node_tree_1` VALUES(10, 2, 5, 0, 'New Page', 6, '4', '', '');

谢谢!

4

1 回答 1

0

鉴于您没有任何不是根节点的直接子节点的兄弟节点,因此您的示例数据很难,但我会处理那里的内容:)

我认为您将需要两个 SQL 调用 - 一个用于获取包含所选节点的左/右值的所有节点,另一个用于使用上一个调用中的“父”左/右值来获取兄弟姐妹您选择的节点

例如,抓取包含目标节点左/右值的所有节点

SELECT e.* FROM exp_node_tree_1 as e, (SELECT lft, rgt FROM exp_node_tree_1 WHERE node_id = ?) AS tbl WHERE (e.lft < tbl.lft) and (e.rgt > tbl.rgt) ORDER BY e.lft ASC

更换 ?使用所选节点的 node_id。这将返回所选节点的所有祖先,从顶层开始,一直到所选节点的直接父节点

第二个查询(兄弟)可以通过两种方式完成,这取决于您是否想使用已经返回的 lft / rgt 值(例如从 PHP 中获取值),或者您是否想在 SQL 中完成繁重的工作。在 SQL 中执行意味着查询更复杂,但除了所选节点的 id 之外,您不需要任何数据

使用来自所选节点的父节点的 PHP 值(在上一个查询中返回)

SELECT * FROM `exp_node_tree_1` WHERE (lft > ?) AND (rgt < ?) ORDER BY lft ASC

换第一个?使用父级的 lft 值,第二个?与父级的 rgt 值

第二种方法只使用选中节点的node_id

select s.* FROM exp_node_tree_1 as s, (SELECT e.lft, e.rgt FROM exp_node_tree_1 as e, (SELECT lft, rgt FROM exp_node_tree_1 WHERE node_id = ?) AS tbl WHERE (e.lft < tbl.lft) and (e.rgt > tbl.rgt) ORDER BY e.lft DESC LIMIT 1) as parent WHERE (s.lft > parent.lft) AND (s.rgt < parent.rgt) ORDER BY s.lft ASC

就像我说的 - 有点复杂。更换 ?使用所选节点的 node_id

希望这可以帮助!

于 2010-11-28T13:26:27.630 回答