Mysql 通过非唯一名称在嵌套集模型中选择节点

Mysql 通过非唯一名称在嵌套集模型中选择节点,mysql,select,nested,set,Mysql,Select,Nested,Set,我试图管理表中节点的检索,不是通过唯一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 n

我试图管理表中节点的检索,不是通过唯一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 +--历史 +--语法 在本例中,上面的查询将返回ARTICLES/PHP/syntax或ARTICLES/JS/syntax:深度为3的“syntax”节点实际上位于PHP节点或JS节点下。
有没有解决这个问题的有效途径?

我不太清楚你在这里想做什么。您正在尝试使用路径名
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回复:在嵌套集中进行直接子匹配并没有多大乐趣。您必须尝试在每个连接行之间选择一个中间父行。这是您不希望存在的行,因此您可以使用null left join反转该条件。例如:

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'

那么,您正在输入例如“PHP”和“syntax”以及它们各自的深度,您想要它们的轨迹到达顶部吗?或者,如果不是这样的话,你想要的确切输入和输出是什么?是的,Wrikken,我正试图做到这一点。我会从给定的路径获取深度。谢谢bobince:这种方法(每个级别的渐进连接)与邻接模型中使用的方法相同,因此嵌套集模型在检索任务中也显示出一些限制,是吗?是的,嵌套集在这里并没有真正的意义。嵌套集使您能够选择满足某种层次关系的多行;在这里,您只想选择一行,因此没有优势。嵌套集的一个操作对于完成上面的查询以获取目标节点的
lft
-非常理想,它将获取该节点的所有祖先,即
SELECT*FROM tbl,其中(节点的lft值)介于lft和rgt
之间。可能我对我的任务解释得不好,但我也需要一个节点及其整个层次结构。当然,我使用嵌套集是为了利用这种技术带来的特殊优势:通过它,我为每个任务编写了适当的分层方法,例如getParents()、getChildren()、getSibbins()等等。用一个给定的ID进行检索不是问题,因为它是一个唯一的标识符,但我希望将检索任务扩展到名称。获取父元素(请求元素的整个层次结构)正是我想要做的。警告:此查询可能会产生无效结果,因为它无法区分
ARTICLES/PHP/syntax
ARTICLES/PHP/legacy/sytnax
,因为这两个路径都满足查询。@Madbreaks:Added,虽然我不一定推荐它,除非你绝望,这是一个不常见的问题。到达嵌套集的合理操作边界!