代码之家  ›  专栏  ›  技术社区  ›  yodabar Arkana

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

  •  2
  • yodabar Arkana  · 技术社区  · 15 年前

    我正在尝试管理中节点的检索 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
    

    在本例中,上面的查询将返回ARTICLES/PHP/syntax或ARTICLES/JS/syntax:实际上,深度为3的“syntax”节点位于PHP节点或JS节点之下。 有没有一条有效的途径去走,去解决这个问题?

    1 回复  |  直到 15 年前
        1
  •  3
  •   bobince    14 年前

    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'