我正在使用mySQL,而且我需要从一个表中选择与父级中任何级别的ID匹配的数据 - >另一个表中的子数据层次结构。
此外,我想用一个编写良好的SQL查询来解决这个问题,而不是我的PHP代码中的递归函数,因为这个功能会被使用很多。
我确实尝试过搜索,我偶然发现了许多类似的问题(大多数问题都得到了解决),但是他们都没有帮助我。
为了帮助说明这种情况,这是我当前的设置
表“文章”:
表类别
我需要选择“articles.category_id”所在的“文章”中的所有文章,比方说,10。但是还要从“categories.category_id”10所属的树中收到所有类别的所有文章。< / p>
意思是,“10”是父母及其所有孩子,其中10岁是孩子及其所有父母。
没有递归的php函数可能吗?
谢谢。
答案 0 :(得分:3)
使用您正在使用的Adjacency List设计,无法在一个查询中获取整个树,因为您使用的是MySQL。
其他一些品牌的数据库支持SQL扩展来处理这种设计。 Oracle,Microsoft SQL Server,IBM DB2和PostgreSQL 8.4(目前处于测试阶段)支持SQL扩展。
存在其他数据库设计,允许您更有效地查询树。这个问题已经在StackOverflow,博客和文章中多次得到解决。
你也可以阅读Joe Celko的“Trees and Hierarchies in SQL for Smarties”,深入研究了几个这样的设计。
答案 1 :(得分:2)
这可以在MySQL
中进行,但需要花费一点力气。你必须写一个这样的函数:
CREATE FUNCTION hierarchy_connect_by_parent_eq_prior_id(value INT) RETURNS INT
NOT DETERMINISTIC
READS SQL DATA
BEGIN
DECLARE _id INT;
DECLARE _parent INT;
DECLARE _next INT;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET @id = NULL;
SET _parent = @id;
SET _id = -1;
IF @id IS NULL THEN
RETURN NULL;
END IF;
LOOP
SELECT MIN(id)
INTO @id
FROM categories
WHERE parent = _parent
AND id > _id;
IF @id IS NOT NULL OR _parent = @start_with THEN
SET @level = @level + 1;
RETURN @id;
END IF;
SET @level := @level - 1;
SELECT id, parent
INTO _id, _parent
FROM categories
WHERE id = _parent;
END LOOP;
END
并在查询中使用它:
SELECT id, parent, level
FROM (
SELECT hierarchy_connect_by_parent_eq_prior_id(id) AS id, @level AS level
FROM (
SELECT @start_with := 0,
@id := @start_with,
@level := 0
) vars, categories
WHERE @id IS NOT NULL
) ho
JOIN categories hi
ON hi.id = ho.id
有关详细信息,请参阅我的博客中的此条目:
答案 2 :(得分:1)
在关系数据库中存储分层数据的最常见模式是相邻列表或modified preorder (aka nested set)。另一种方法是使用物化路径,它基本上是一种缓存机制,位于相邻列表的顶部。另请参阅this table for a comparison of pros and cons。
答案 3 :(得分:0)
我不知道这对你有多大帮助,但我写了一个小函数,它使用一个MySQL查询生成一个分层树。基本上,所有重要的逻辑都转移到了PHP中。我的解决方案使用邻接列表模型,然后使用PHP引用,以便通过平面建立树数据结构。看看下面的要点,看看你是否有一些灵感。我会帮助你更多,但在我的工作中我必须面对一些问题。