5

我正在使用一个实现了单链表(id,parent)的表。这个实现一直运行良好,但最近性能变得难以忍受,因为我的列表越来越长并且我一直在单独查询节点。

我发现了一篇关于如何在单个查询中进行查询的有前途的博客。http://explainextended.com/2009/03/25/sorting-lists/

SELECT  @r AS _parent,
        @r := (
        SELECT  id
        FROM    t_list
        WHERE   parent = _parent
        ) AS id
FROM    (
        SELECT  @r := 0
        ) vars,
        t_list

唯一的问题是我对 MySQL 不够了解,甚至无法使用它。我的问题与我在博客评论中发布的问题相同。如何设置从哪个记录/节点开始?就像我想从示例表中的 id 3 开始一样。它如何知道何时到达列表末尾并应该停止?我已经尝试过了,它永远运行(可能是由于与前一个问题相关的不当使用)。

谢谢。

4

1 回答 1

5

该查询通过迭代表t_list(最后一行)来工作。对于该表中的每一行,SELECT子句中的子查询重新查询该表,搜索当前行的子行(WHERE parent = _parent-- 但是_parent是 的别名@r)。在每次迭代中,孩子的id被分配给@r变量。

要添加边界,这种变化应该可以解决问题:

SELECT * FROM (
    SELECT
        @r AS _parent,
        @r := (
            SELECT id
            FROM t_list
            WHERE
                ( @c = 0 AND _parent IS NULL AND parent IS NULL ) -- special case if the first item is the root
                OR (parent = _parent)
        ) AS id,
        @c := @c + 1 AS rank
    FROM (
        SELECT @c := 0, @r := parent FROM t_list WHERE id = @start
    ) AS ini,
    (
        SELECT id FROM t_list LIMIT @limit
    ) AS lim
) AS tmp WHERE id IS NOT NULL;

@start和分别@limit替换id为第一个项目的 和要检索的最大项目数。请在这里测试


使用 RDBMS 对这样的数据结构进行建模可能完全是个坏主意。为什么不只使用“索引”列?获取列表然后变得即时:

SELECT * FROM list ORDER BY index_column ASC;

也许您的列表应该经常更改,但是这样的查询应该相当快,除非列表变得非常大:

-- insert an element at position X 
UPDATE list SET index_column = index_column +1 WHERE index_column > X ORDER BY index_column DESC;
INSERT INTO list VALUE (some_value, X);

-- delete an element at position X 
DELETE FROM list WHERE index_column = X;
UPDATE list SET index_column = index_column -1 WHERE index_column > X ORDER BY index_column ASC;
于 2013-07-08T22:53:54.187 回答