3

我有一个问题,上周正在处理这个问题,但还没有解决。我可以用 join 查询子菜单,但我不能订购它。

我有一张这样的桌子

| 编号 | 姓名 | 家长 | 订购 |    
|--------------------------------------------|
| 1 | 菜单1 | 0 | 1 |
| 2 | 子菜单1 | 1 | 2 |
| 3 | 子菜单2 | 1 | 1 |
| 4 | 子菜单 | 2 | 1 |
| 5 | 子子菜单:) | 4 | 1 |
| 6 | 菜单2 | 0 | 3 |
| 7 | 菜单3 | 0 | 2 |
|--------------------------------------------|

我想得到这样的东西。

| - 菜单1
      | - 子菜单2
      | - 子菜单1
              | - 子菜单
                       | - 子子菜单:)
| - 菜单3
| - 菜单2

谁能给我一个想法如何处理这个?谢谢

4

3 回答 3

1

我研究了http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/并找到了解决您问题的方法。我想你已经有了你的解决方案,但是对于任何其他正在寻找相同解决方案的人,我在这里回答。

我的解决方案也适用于关系表,因为我们不能在关系表的父字段中设置零 (0)。它将为 NULL,我的解决方案也适用于关系表。

功能

DROP FUNCTION IF EXISTS hierarchy_connect_by_parent_eq_prior_id;
DELIMITER $$
CREATE FUNCTION hierarchy_connect_by_parent_eq_prior_id(value INT) RETURNS INTEGER
NOT DETERMINISTIC
READS SQL DATA
BEGIN
    DECLARE _parent INT;
    DECLARE _rank INT;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET @id = NULL;

    SET _parent = @id;
    SET _rank = 0;

    IF @id IS NULL THEN
            RETURN NULL;
    END IF;

    LOOP
        SET @innerrank = 0;
        SELECT p.id 
        INTO   @id
        FROM   (
                SELECT   id, @innerrank := @innerrank+1 AS rank 
                FROM     yourTable 
                WHERE    COALESCE(parent, 0) = _parent 
                ORDER BY yourField
                ) p 
        WHERE   p.rank > _rank LIMIT 0, 1;
        IF @id IS NOT NULL OR _parent = @start_with THEN
                SET @level = @level + 1;
                RETURN @id;
        END IF;
        SET @level := @level - 1;
        SET @innerrank = 0;
        SELECT COALESCE(p.parent, 0), p.rank
        INTO   _parent, _rank
        FROM   (
                SELECT id, parent, @innerrank := @innerrank+1 AS rank
                FROM    yourTable
                WHERE   COALESCE(parent, 0) = (
                    SELECT COALESCE(parent, 0) FROM yourTable WHERE id = _parent
                    ) 
                ORDER BY yourField
               ) p
        WHERE p.id = _parent;
    END LOOP;       
END;
$$
DELIMITER ;

请替换yourTable为您的表格名称和yourField您想要对数据进行排序的字段名称。

查询

SELECT ou.* FROM (
    SELECT hi.id, parent, yourField 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, yourTable 
            WHERE @id IS NOT NULL
        ) ho 
    JOIN yourTable hi ON hi.id = ho.id
) ou

请替换yourTable为您的表格名称和yourField您要显示的字段名称。

这将产生您需要的结果。我对其进行了测试并且效果很好。

这是http://sqlfiddle.com/#!9/9d060d/2以查看它的实际效果。

于 2015-05-27T07:56:56.747 回答
0

你不能用一个查询来做到这一点。只需在您选择的脚本语言中使用递归

class Hierarchy

    function __construct(db)
        db = db.connect
        this.stmt = db.prepare "SELECT name FROM Hierarchy WHERE parent = ?"
        this.tree = {}
    end

    function getHierarchyFromParent(parent = 0, tree = null)
        tree = this.tree if tree is null
        while result = this.stmt.execute(parent).fetch
            tree[result.name] = {
                children: this.getHierarchyFromParent result.id tree[result.name]
            }
        end
    end
end
于 2013-04-06T14:38:21.023 回答
0

根据您的回答 - 您希望将结果放在一个平面列表中。在这种情况下,我会说最有效的方法是确保您更改订单策略,您将在选择商品时避免不必要的复杂性和开销。如果您的订购也基于平面列表,您将解决问题:

| id   |  name           |  parent | order  |    
|-------------------------------------------|
| 1    | menu1           |  0      |   1    |
| 2    | submenu1        |  1      |   2    |
| 3    | submenu2        |  1      |   3    |
| 4    | subsubmenu      |  2      |   4    |
| 5    | subsubsubmenu:) |  4      |   5    |
| 6    | menu2           |  0      |   6    |
| 7    | menu3           |  0      |   7    |
|-------------------------------------------|

实现这样的排序并不难。

于 2013-04-06T14:47:15.453 回答