2009-06-25 6 views
2

인접성 목록/단일 테이블 상속 모델 (id, parent_id)을 사용하여 데이터베이스에서 모든 부모 요소를 재귀 적으로 가져 오는 가장 간단한 방법을 찾고 있습니다. mysql/php에서 id/parent_id 모델을 사용하여 레코드의 모든 부모를 얻는 가장 간단한 방법은 무엇입니까?

$sql = "SELECT 
      e.id, 
      TIME_FORMAT(e.start_time, '%H:%i') AS start_time, 
      $title AS title, 
      $description AS description, 
      $type AS type, 
      $place_name AS place_name, 
      p.parent_id AS place_parent_id, 
      p.city AS place_city, 
      p.country AS place_country 
     FROM event AS e 
     LEFT JOIN place AS p ON p.id = e.place_id       
     LEFT JOIN event_type AS et ON et.id = e.event_type_id 
     WHERE e.day_id = '$day_id' 
     AND e.private_flag = 0 
     ORDER BY start_time"; 

eventplace에 연결되어, 각 place 다른 place (깊이 약 5 개까지 수준)

의 자녀가 될 수이 가능

:

현재 선택 나의은 다음과 같습니다 mysql을 이용한 단일 select?

현재로서는 $events 배열을 반복하는 별도의 함수가 될 수 있다고 생각하고 있으므로 place_parent_X 요소를 추가하지만이를 구현하는 방법을 모르겠다.

답변

0

표준 부모 - 자식 DB 디자인으로는 불가능합니다.

그러나 nested set 접근 방식을 사용하여 하나의 쿼리에서 수행 할 수 있지만 그 시점까지 도달하는 데는 많은 작업이 필요합니다.

+1

중첩 된 세트는 db 스키마에서 변경해야하며, 이는 내 경우에는 가능하지 않습니다. – meleyal

+0

예. 그렇다면 MySQL (액세스 권한이 없을 수도 있음)이나 PHP (지저분하고 느린)에서 재귀 적 접근 방식을 사용해야합니다. –

+0

지저분하고 느린 것은 괜찮을 것입니다, 나는 단지 그것을하는 방법에 대한 몇 가지 조언이 필요합니다;) – meleyal

7

MySQL에서이를 수행 할 수 있지만 기능을 만들어 검색어로 사용해야합니다.

CREATE FUNCTION hierarchy_connect_by_parent_eq_prior_id(value INT) RETURNS INT 
NOT DETERMINISTIC 
READS SQL DATA 
BEGIN 
     DECLARE _id INT; 
     DECLARE _parent INT; 
     DECLARE _next INT; 
     DECLARE CONTINUE HANDLER FOR NOT FOUND SET @id = NULL; 

     SET _parent = @id; 
     SET _id = -1; 

     IF @id IS NULL THEN 
       RETURN NULL; 
     END IF; 

     LOOP 
       SELECT MIN(id) 
       INTO @id 
       FROM place 
       WHERE parent = _parent 
         AND id > _id; 
       IF @id IS NOT NULL OR _parent = @start_with THEN 
         SET @level = @level + 1; 
         RETURN @id; 
       END IF; 
       SET @level := @level - 1; 
       SELECT id, parent 
       INTO _id, _parent 
       FROM place 
       WHERE id = _parent; 
     END LOOP; 
END 

SELECT id, parent 
FROM (
     SELECT hierarchy_connect_by_parent_eq_prior_id(id) AS id, @level AS level 
     FROM (
       SELECT @start_with := 0, 
         @id := @start_with, 
         @level := 0 
       ) vars, t_hierarchy 
     WHERE @id IS NOT NULL 
     ) ho 
JOIN place hi 
ON  hi.id = ho.id 

후자의 쿼리의 모든 자손을 선택합니다 : 여기

  • Hierarchical queries in MySQL
  • 함수 쿼리입니다

    은 자세한 설명에 대한 내 블로그에서이 항목을 참조하십시오 주어진 노드 (@start_with 변수에 설정해야 함)

    ,363,210

    는 기능없이 간단한 쿼리를 사용하여 주어진 노드의 모든 조상을 찾는 방법은 다음과 같습니다

    : 내 블로그에이 기사 더 자세히이 쿼리를 설명
    SELECT @r AS _id, 
         @r := (
         SELECT parent 
         FROM place 
         WHERE id = _id 
         ) AS parent 
    FROM (
         SELECT @r := @node_id 
         ) vars, 
         place 
    

    두 가지 솔루션 모두 합리적인 시간 내에 작동하려면 idparent에 인덱스가 있어야합니다.

    idPRIMARY KEY으로 정의되어 있고 parent에 보조 색인이 있어야합니다.

+0

블로그에 링크를 해주시겠습니까? – razzed

+0

@razzed : 잠시 후, 죄송합니다 :) – Quassnoi

+0

두 번째 쿼리는 좋아 보이는데, 더 자세히 설명 할 수 있습니까? – meleyal