2013-07-08 6 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; 

은 첫 번째 항목의 id@start@limit을 교체하고있는 항목 수가 최대 개수는 각각 검색 :

이 변화가 트릭을 할해야, 경계를 추가합니다. 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

도와 드리겠습니다. 여유 시간이 있다면, [이 답변]에서 제안 된 것처럼 간단한 'JOIN'과 비교하여 짧은 데이터 범위 (예 : 10 개 항목)에서이 쿼리가 어떻게 수행되는지 알고 싶습니다. http://stackoverflow.com/a/675184/1446005)에서 비슷한 질문을합니다. – RandomSeed