【发布时间】:2025-12-25 16:45:07
【问题描述】:
我的数据库中有一个表,我使用混合嵌套集 (MPTT) 模型(具有 lft 和 rght 值的模型)和邻接列表模型(存储 parent_id on每个节点)。
my_table (id, parent_id, lft, rght, alias)
这个问题与树的任何 MPTT 方面都没有关系,但我想我会留下它,以防有人知道如何利用它。
我想将别名路径转换为特定节点。例如:"users.admins.nickf" 会找到别名为“nickf”的节点,该节点是别名为“admins”的节点的子节点,而别名“admins”是位于根目录下的“users”的子节点。 (parent_id, alias) 上有一个唯一索引。
我从编写函数开始,以便将路径拆分为各个部分,然后逐个查询数据库:
SELECT `id` FROM `my_table` WHERE `parent_id` IS NULL AND `alias` = 'users';-- 1
SELECT `id` FROM `my_table` WHERE `parent_id` = 1 AND `alias` = 'admins'; -- 8
SELECT `id` FROM `my_table` WHERE `parent_id` = 8 AND `alias` = 'nickf'; -- 37
但后来我意识到我可以通过一个查询,使用可变数量的嵌套来做到这一点:
SELECT `id` FROM `my_table` WHERE `parent_id` = (
SELECT `id` FROM `my_table` WHERE `parent_id` = (
SELECT `id` FROM `my_table`
WHERE `parent_id` IS NULL AND `alias` = 'users'
) AND `alias` = 'admins'
) AND `alias` = 'nickf';
由于子查询的数量取决于路径中的步骤数,我是否会遇到子查询过多的问题? (如果有这种事)
有没有更好/更智能的方法来执行这个查询?
【问题讨论】:
-
何不建个测试表,看看查询(递归)栈有多深?
-
不能首先使用最具辨别力的选择器('nickf')'感觉不对'..也许你通过加入查询而不是使用子查询来构建它?这将避免递归(不是真的,但看起来像)=>级联自加入!
-
出于好奇,我写了“自加入级联”.. 看看我的答案。
标签: sql mysql tree adjacency-list mptt