如何在同一查询中选择所有直接子项和祖先

Tra*_*vis 6 mysql sql tree nested-sets hierarchical-data

我正在使用MySQL中的树结构,使用嵌套集模型重新呈现.

我希望你们中的一些SQL专家可以帮我构建一个SELECT查询.

我希望能够使用LIKE匹配一组节点.对于匹配的每个节点,我还需要该节点的祖先的逗号分隔列表,以及该节点的直接子节点的逗号分隔列表.

我不确定从哪里开始 - 如果在单个查询中甚至可以实现这样的事情.(目前我在循环中使用查询来完成此操作.)我希望的是一个看起来像这样的结果集....

从字符串"qu"开始并查询表"Body"我得到...

Node      | Parent Nodes               | Immediate Children
Quads       Leg, Lower Body, Muslces     Vastus Lateralus, Vastus Medialis, Rectus Femoris
Obliques    Core, Trunk, Muscles         Inner obliques, outer obliques
Run Code Online (Sandbox Code Playgroud)

如何在不循环查询的情况下完成此任何建议将非常感激.

Rol*_*man 0

虽然我同意 nickf 的观点,认为这既糟糕又肮脏,但它仍然很有趣,所以这里是:

SELECT     base.left_id, base.ancestors, 
           GROUP_CONCAT(children.left_id) children
FROM       (
            SELECT     base.left_id
            ,          GROUP_CONCAT(ancestors.left_id) ancestors
            FROM       nested_set   base
            LEFT JOIN  nested_set   ancestors
            ON         base.left_id     BETWEEN ancestors.left_id 
                                            AND ancestors.right_id
            WHERE      base.name  LIKE '%criteria%'
            GROUP BY   base.left_id
           ) base                                    
LEFT JOIN  nested_set   children
ON         children.left_id BETWEEN base.left_id 
                                AND base.right_id
LEFT JOIN  nested_set   inbetween
ON         inbetween.left_id BETWEEN base.left_id 
                                AND base.right_id
AND        children.left_id  BETWEEN inbetween.left_id 
                                AND inbetween.right_id     
WHERE      inbetween.left_id IS NULL
GROUP BY   base.left_id
Run Code Online (Sandbox Code Playgroud)

基本上,诀窍是分两步解决:首先,解决祖先问题,并将祖先压缩到一个列表中,然后用这个结果为孩子们解决它。

祖先部分相对简单,它是我的解决方案中 from 子句中的子查询。孩子们就有点难了。它的工作原理是获取所有后代,然后要求基节点和后代之间不存在任何节点,这基本上将后代限制为仅限子节点。

此策略还有其他变体可以解决此问题 - 例如,您可以先处理子项,然后使用列表中的子查询来解决祖先项SELECT