2009-08-26 3 views
1

트리 구조를 구성하는 항목을 포함하는 데이터베이스 테이블 (sqlite)이 있습니다. 각 항목에는 id 필드 (자체 용) 및 해당 부모 용 parentId이 있습니다. 이제 항목이 주어지면 루트에서 항목까지 전체 체인을 검색해야합니다. 같은몇 개의 SQL 쿼리가 필요합니까?

는 기본적으로 의사의 알고리즘은 같습니다 커서가 항목 입니다

  1. 이 parentItem이 rootItem하지 않은 경우, 다음 = parentItem와 고토 커서
  2. parentId가 커서 parentItem를 검색 2.

그래서 각 항목에 대해 SQL SELECT 쿼리를 수행해야합니다.

하나의 SQL 쿼리 만 수행하여 전체 체인 rootItem -> ... -> 항목을 검색 할 수 있습니까?

답변

0

ANSI 표준 SQL이 아닌 것은 아닙니다. 그건 사실이 아니에요. 왼쪽 외부 조인을 수행하고 가능한 최대 깊이를 충당하기에 충분하지만 최대 깊이를 제한하지 않고 많은 조인을 포함하지 않으면 항상 작동하지는 않습니다.

행 세트가 충분히 작 으면 (예 : 1000 개 미만), 모두 검색하여 알아낼 수 있습니다. 모든 읽기에서 단일 읽기 탐색보다 빠릅니다.

부모 탐색을 일괄 처리 할 수 ​​있습니다. 다음과 같은 검색어를 사용하십시오.

SELECT t1.id id1, t1.parent parent1, 
     t2.id id2, t2.parent parent2, 
     t3.id id3, t3.parent parent3, 
     t4.id id4, t4.parent parent4, 
     t5.id id5, t5.parent parent5 
FROM mytable t1 
LEFT OUTER JOIN mytable t2 ON t1.parent = t2.id 
LEFT OUTER JOIN mytable t3 ON t2.parent = t3.id 
LEFT OUTER JOIN mytable t4 ON t3.parent = t4.id 
LEFT OUTER JOIN mytable t5 ON t4.parent = t5.id 
WHERE t1.id = 1234 

원하는 번호로 확장하십시오. 마지막으로 검색된 상위가 null이 아니면 트리의 맨 위에 있지 않으므로 쿼리를 다시 실행하십시오. 이렇게하면 1-2 왕복으로 갈아 타야합니다.

그 외에도 ID의 해당 데이터를 인코딩하는 방법을 살펴볼 수 있습니다. 이것은 권장하지 않지만 각 노드의 어린이 수가 100 명이라고 가정하면 ID가 10030711 인 노드의 경로는 10 -> 03 -> 07 -> 11입니다. 물론 다른 문제가 있습니다 (예 : max ID 길이) 그리고 물론 그것은 해킹입니다.

SQL의 계층 적 데이터에는 두 가지 기본 모델이 있다는 점도 유의해야합니다. 인접 목록 및 중첩 세트. 귀하의 방식 (꽤 일반적인)은 인접 세트입니다. 중첩 된 세트는 실제로 이러한 상황에 도움이되지 않으며 삽입 작업을 복잡하게합니다.

+0

불행하게도 행 내 세트가 합리적으로 크고도 지속적으로 성장하고 다음 링크를 참조하십시오. –

2

데이터베이스에서 계층 적 데이터를 체계적으로 구성하는 방법은 많이 있지만 일관되게 가장 쉬운 방법은 데이터를 비 계층 적 형식으로 되돌리고 부모 및 자식 레코드를 프로그래밍 방식으로 일치시키는 것입니다.

총 작업량 : 1 쿼리 + 1 프로그래밍 방식으로 데이터 집합을 통과하여 계층을 만듭니다.


대체 접근 방식은 :

내가 제한된 성공 과거에이 방법을 사용했습니다.ID = 5에서 모든 노드를 매우 간단한되어지고, 그 시점에서

ID ParentID Path 
-- -------- ---- 
1  null  1/ 
2  1   1/2/ 
3  null  3/ 
4  2   1/2/4/ 
5  4   1/2/4/5/ 
6  null  6/ 
7  5   1/2/4/5/7/ 
9  5   1/2/4/5/9/ 

: 당신은 다음과 같이 VARCHAR (최대) 열을 사용하여 트리의 각 항목의 경로를 저장할 수 있습니다

SELECT * 
FROM table 
WHERE Path like (SELECT Path FROM Table WHERE ID = 5) + '%' 
+0

좋은 기술, 나는 그것을 +1 하겠지만 나는 몇 시간 동안 투표에서 벗어났다. 왜 당신은 ** 제한된 ** 성공을 말합니까? –

+0

왜 그냥 SELECT * FROM 테이블 WHERE Path LIKE '%/5/%'; ? –

+0

@eyze : 물론 가능합니다. :) 그러나 거의 모든 데이터베이스 구현에서 데이터베이스는 와일드 카드 문자로 시작하는 식과 같은 식의 인덱스를 사용할 수 없습니다. SQLite 설명서 (http://www.sqlite.org/optoverview.html)를 참조하십시오 : "LIKE 또는 GLOB 연산자로 구성된 용어는 때때로 인덱스를 제한하는 데 사용될 수 있습니다.이 용도에는 많은 조건이 있습니다. .] LIKE 또는 GLOB의 오른쪽은 와일드 카드 문자 "로 시작하지 않는 문자열 리터럴이어야합니다. 위의 코드는 문자열 리터럴이 아니기 때문에 인덱스를 사용하는 것이 확실하지 않습니다. YMMV. – Juliet

0

테이블 구조를 변경할 수 있습니까? 왼쪽과 오른쪽 노드를 저장하는 것이 한 번의 선택 만 가능하기 때문에 부모 노드를 저장하는 것보다 쉽게 ​​작업 할 수 있습니다. (이 SQLServer에,하지만 그들은 도움이 될 수도 있습니다.)

http://www.mail-archive.com/[email protected]/msg23867.html

http://weblogs.asp.net/aghausman/archive/2009/03/16/storing-retrieving-hierarchical-data-in-sql-server-database.aspx

관련 문제