2010-09-27 59 views
2

我试图来管理节点的检索在nested set model表,而不是通过唯一的ID,但通过名称(串),和不同父母下的树内的其他节点可以被调用相同的方式。选择在嵌套集模型的节点通过未唯一的名称

至于现在,我使用的唯一的ID来获得嵌套组内的节点:

SELECT 
    node.name, node.lft, node.rgt 
FROM tbl AS parent, tbl AS node 
WHERE node.lft BETWEEN parent.lft AND parent.rgt 
AND node.id = '{$node_id}' 
GROUP BY node.id

尝试此方法扩展到更一般的方法来检索通过其名称的节点,我想出了含有多达HAVING子句为节点的深度查询检索,检查节点名称和它的深度:

SELECT 
    node.name, node.lft, node.rgt, COUNT(node.id) AS depth 
FROM tbl AS parent, tbl AS node 
WHERE node.lft BETWEEN parent.lft AND parent.rgt 
GROUP BY node.id 
HAVING 
    (node.name = 'myParentName' AND depth = 1) 
    OR 
    (node.name = 'myParent2Name' AND depth = 2) 
    OR 
    ... 
# and so on 

但它并非十全十美:具有相同的名称和相同深度的两个节点,但是在不同的父母身上,无论是否等级高,都可以被检索出来他们属于。

实施例:

 
ARTICLES 
    | 
    +--PHP 
    | +--the-origins 
    | +--syntax 
    +--JS 
     +--history 
     +--syntax 

在这种情况下,上面的查询将返回任一文章/ PHP /语法或制品/ JS /语法:具有深度3,事实上一“语法”节点,或者是下PHP节点或JS节点下。 有没有一条有效的路径来解决这个问题?

+0

因此,您正在输入例如'PHP'和'语法'及其各自的深度,并且您希望他们的路径位于顶部?或者,如果情况并非如此,那么您需要什么确切的输入和输出? – Wrikken 2010-09-27 20:06:55

+0

是的Wrikken,我正在努力做到这一点。我会从给定的路径深度。 – 2010-09-27 21:11:11

回答

3

我不太确定你要在这里做什么。您是否试图访问路径名为ARTICLES/PHP/syntax的节点?如果是这样你需要做的将是每个父母级别自联接:

SELECT n0.* 
FROM tbl AS n0 
JOIN tbl AS n1 ON n0.lft BETWEEN n1.lft+1 AND n1.rgt 
JOIN tbl AS n2 ON n1.lft BETWEEN n2.lft+1 AND n2.rgt 
WHERE n0.name='syntax' AND n1.name='PHP' AND n2.name='ARTICLES' 

ETA重新注释:做直子在嵌套组比赛是不是很有趣。您必须尝试在每个连接的行之间选择一个中间父行。这是你不想存在的行,所以你然后用空的左连接反转这个条件。例如:

SELECT n0.* 
FROM tbl AS n0 
JOIN tbl AS n1 ON n0.lft BETWEEN n1.lft+1 AND n1.rgt 
JOIN tbl AS n2 ON n1.lft BETWEEN n2.lft+1 AND n2.rgt 
LEFT JOIN tbl AS nn1 ON nn1.lft BETWEEN n1.lft+1 AND n0.lft-1 
LEFT JOIN tbl AS nn2 ON nn2.lft BETWEEN n2.lft+1 AND n1.lft-1 
WHERE nn1.lft IS NULL AND nn2.lft IS NULL 
AND n0.name='syntax' AND n1.name='PHP' AND n2.name='ARTICLES' 
+0

感谢bobince:这个方法(每个级别的渐进式JOINs)与adjacendy模型中使用的相同,所以嵌套集合模型在检索任务中也显示出一些限制,是不是? – 2010-09-27 21:11:45

+0

是的,嵌套集合在这里并没有给你带来任何好处。嵌套集让您能够选择满足某些层次关系的行数;在这里,你只想选择一行,所以没有优势。嵌套集合的操作对于完成上面的查询以获得目标节点的'lft'将是理想的 - 将获得该节点的所有祖先,这将是'SELECT * FROM tbl WHERE(节点的lft值)BETWEEN lft和rgt'。 – bobince 2010-09-27 21:54:36

+0

可能我解释得不好我的任务,但我也需要一个节点及其整个层次结构。当然,我正在使用嵌套集合来利用这种技术带来的特定优势:通过它,我为每个任务(例如getParents(),getChildren(),getSiblings())编写了适当的分层方法。由给定的ID来执行它不是问题,因为它是唯一的标识符,但我希望将检索任务扩展到名称。获得父母(所请求元素的整个层次结构)正是我想要做的。 – 2010-09-29 10:40:23