2009-09-23 3 views
2
나는 나무/조상/쿼리 문제가

에 메뉴 테이블에서 일치하는 메뉴 트리 데이터를 얻기 메뉴 :내가 해결할 수 아니에요 MySQL을

table menu    table ancestors 
+-----+------------+--------+  +---------+--------------+-------+ 
| id |  title | active |  | menu_id | ancestor_id | level | 
+-----+------------+--------+  +---------+--------------+-------+ 
| 1 |  Home |  0 |  |  1 |   0 |  0 | 
| 2 |  News |  0 |  |  2 |   1 |  1 | 
| 3 |  Foo |  0 |  |  3 |   2 |  2 | 
| 4 |  Bar |  1 |  |  3 |   1 |  1 | 
| 5 | Downloads |  1 |  |  4 |   3 |  3 | 
+-----+------------+--------+  |  4 |   2 |  2 | 
            |  4 |   1 |  1 | 
            |  5 |   1 |  1 | 
            +---------+--------------+-------+ 

내가 그들의 조상의 모든 활성 메뉴 항목을 쉽게 얻을 :

SELECT menu.id, menu.title, GROUP_CONCAT(ancestors.ancestor_id) as ancestors 
FROM menu, ancestors 
WHERE menu.active = 1 
GROUP BY (menu.id); 

+----+-----------+----------+ 
| id |  title |ancestors | 
+----+-----------+----------+ 
| 4 |  Bar | 3,2,1 | 
| 5 | Downloads | 1  | 
+----+-----------+----------+ 

하지만 어떻게 모든 나무 필요한 조상에 대한도받을 수 있나요? 내 결과에서 일관된 나무를 얻을 수 있도록 Foo와 News 항목이 필요합니다. 이 형식은 다음과 같아야합니다.

+----+-----------+----------+ 
| id |  title |ancestors | 
+----+-----------+----------+ 
| 2 |  News | 1  | 
| 3 |  Foo | 2,1  | 
| 4 |  Bar | 3,2,1 | 
| 5 | Downloads | 1  | 
+----+-----------+----------+ 

쿼리의 모양은 어떻습니까?

답변

1

이렇게하면 ancestors 테이블을 약간 다르게 구성합니다. level 대신 pathlength을 저장합니다. 각 메뉴 항목이 자신을 가리 키도록하기위한 또한 이러한 "재귀"항목은 폐쇄 테이블 활성 메뉴 항목의 설정에 가입 할 수 있도록 0

+---------+--------------+------------+ 
| menu_id | ancestor_id | pathlength | 
+---------+--------------+------------+ 
|  1 |   1 |   0 | 
|  2 |   2 |   0 | 
|  3 |   3 |   0 | 
|  4 |   4 |   0 | 
|  5 |   5 |   0 | 
|  2 |   1 |   1 | 
|  3 |   2 |   2 | 
|  3 |   1 |   1 | 
|  4 |   3 |   3 | 
|  4 |   2 |   2 | 
|  4 |   1 |   1 | 
|  5 |   1 |   1 | 
+---------+--------------+------------+ 

의 경로 길이, 행을 저장합니다. 레벨을 경로 길이로 변경하면 반사 항목을 조상 세트에서 제외 할 수 있습니다.

지금 활성 메뉴 항목 자체를 포함하여 "활성"메뉴 항목의 조상 모든 메뉴 항목을 조회 할 수 있습니다

SELECT a2.menu_id, m2.title, GROUP_CONCAT(a2.ancestor_id) AS ancestors 
FROM menu m1 
JOIN ancestors a1 ON (m1.id = a1.menu_id) 
JOIN ancestors a2 ON (a1.ancestor_id = a2.menu_id AND a2.pathlength > 0) 
JOIN menu m2 ON (a2.menu_id = m2.id) 
WHERE m1.active = 1 
GROUP BY a2.menu_id; 

결과 :

+---------+-----------+-----------+ 
| menu_id | title  | ancestors | 
+---------+-----------+-----------+ 
|  2 | News  | 1   | 
|  3 | Foo  | 2,1  | 
|  4 | Bar  | 3,2,1  | 
|  5 | Downloads | 1   | 
+---------+-----------+-----------+ 
+0

이봐 빌, 덕분에 많이, 내가 찾던 바로 그걸로! – acme

+0

감사 빌. 경로 길이 열에 값을 어떻게 가져 옵니까? SQL Antipatterns 책에서 삽입 및 업데이트 쿼리를 사용하고 있습니다. 감사! –

+0

청구서에 귀하의 답변이 사이트의 댓글에서 발견되었습니다. 그것은 여기에서 찾을 수 있습니다 : [링크] (http://karwin.blogspot.com/2009/04/sql-antipatterns-strike-back-slides.html?showComment=1241892180000#c5106197584960617122) 정말 고마워요! –

관련 문제