2013-07-08 92 views
4

我正在使用已實現單鏈表(id,父)的表。這個實現一直運行良好,除非最近性能變得無法忍受,因爲我的列表變長了,而且我一直在單獨查詢節點。mysql查詢鏈表

我發現了一個很有前途的博客,關於如何在單個查詢中進行查詢。 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開始一樣。它如何知道它何時到達列表的末尾並應該停止?我已經試過了,它只是永遠運行(可能是由於與前一個問題相關的不當使用)。

謝謝。

+0

請您發表您的設置在http://sqlfiddle.com或只准備數據庫轉儲? – Quassnoi

回答

4

該查詢的工作原理是遍歷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,以及項目的最大數量來檢索,分別。請test it here


用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; 
+0

我將爲我自己的未來數據庫考慮這一戰略。它更簡單。不幸的是,我無法控制數據庫模式,所以我必須使這個鏈表查詢正常工作。這些列表通常長1-3k個節點,並且頻繁變化。 – btd

+1

不錯。 :)你已經救了我。 – btd

+0

很高興爲您提供幫助。如果你有一些時間空閒,我很想知道這個查詢如何在一個大的數據集上執行,但在一個短的範圍內(例如10個條目),與[本答案]中建議的簡單'JOIN'相比( http://stackoverflow.com/a/675184/1446005)到一個類似的問題。 – RandomSeed