2011-11-01 9 views
12

나는 테이블 People을 가지고 있습니다. 모든 부모로 구성된 HTML 표를 직접 표시하고 싶습니다.각 부모의 자녀 모두 표시

_________ 
|People |_____________________________________________ 
|-------------------------------------------------------| 
| id  | parent | firstname  | lastname   | 
|-------------------------------------------------------| 
| 1  0  James   Donovan    | 
| 2  0  Jeffrey   Williams   | 
| 3  0  Emmit   Herring    | 
| 4  2  Carol   Williams   | 
| 5  2  Sarah   Williams   | 
| 6  1  Nikolai   Donovan    | 
|_______________________________________________________| 

예상 출력 :

________________________________________________ 
|Jeffrey Williams        | 
|------------------------------------------------| 
| - Carol Williams        | 
| - Sarah Williams        | 
|________________________________________________| 
|James Donovan         | 
|------------------------------------------------| 
| - Nikolai Donovan        | 
|________________________________________________| 
|Emmit Herring         | 
|------------------------------------------------| 
|________________________________________________| 

가 어떻게 반복 설정 올바른 결과를 포함하는 연관 배열을 만들 수 있습니까? 올바른 SQL과 올바른 PHP가 최종 배열을 작성하는 것에 대해 혼란스러워합니다.

특히 두 개의 MySQL 테이블간에 계층 적 관계를 표시하는 방법을 잘 모르겠습니다. SQL 결과 세트는 제가 아는 한 다차원 적이 지 않습니다. for 루프에 SQL 쿼리를 넣는 것은 성능면에서 좋지 않습니다. 그럼 어떻게 하시겠습니까?

MySQL에서 인접성 목록 구현을 찾고 있습니다.

모든 것을 두 테이블로 나눌 수 있다면이 질문은 쉬워야하지만 불행히도이 비정상적인 테이블 구조를 고수해야합니다.

+0

jquery right를 사용할 수 있나요 ?? – defau1t

+0

jQuery를 사용하여 각 부모의 자식처럼 간단하게 표시해야하는 이유는 무엇입니까? 여기에 PHP 솔루션이 있습니까? –

+0

@Mark 내 질문에 충분히 명확하지 않았던 것 같습니다. 나는 숙제 도움을 위해 여기 있지 않습니다. 나는 그 질문을 갱신했다. –

답변

13

그것을 할 방법에는 여러 가지가 있습니다 :

1 명백한 사람은 우선 부모의 목록을 가져 오기, 다음의 각 부모의 자녀에 대해 별도의 쿼리를 실행하는 것입니다 고리. 당신은 이것이 "성능면에서 끔찍한"것이라고 말하지만, parent 컬럼에 인덱스가 있고 MySQL 서버가 행성의 다른쪽에 위치하지 않는다고 가정하면 실제로는 안됩니다.


2 당신이 정말로 이렇게 할 경우

는 단일 쿼리에, 당신은 그 자체에 대해 테이블에 LEFT JOIN를 사용할 수 있습니다

SELECT 
    p.id AS parent_id, 
    p.firstname AS parent_firstname, 
    p.lastname AS parent_lastname, 
    c.id AS child_id, 
    c.firstname AS child_firstname, 
    c.lastname AS child_lastname 
FROM 
    People AS p 
    LEFT JOIN People AS c ON c.parent = p.id 
WHERE p.parent = 0 
ORDER BY p.id 

을 다시 말하지만, 정말 정말parent 열에 색인이 필요합니다. ORDER BY 조항은 각 부모의 자녀가 함께 정렬되도록 보장합니다. 예를 들어 변경할 수 있습니다. 이름을 알파벳순으로 정렬하려면 p.lastname, p.firstname, p.id, c.lastname, c.firstname, c.id과 같이 입력하십시오.

$res = mysql_query($sql); 
$last_parent_id = 0; 
while ($row = mysql_fetch_object($res)) { 
    if ($row->parent_id != $last_parent_id) { 
     // print parent header 
     $last_parent_id = $row->parent_id; 
    } 
    if ($row->child_id) { 
     // print child row 
    } 
} 

: 부모 ID 변경과 같은, 뭔가 (및하여 child_* 열이 NULL입니다 사건을 처리하기 위해 기억) 할 때마다 PHP에서는 다음 새로운 헤더를 결과를 반복 할 필요 인쇄 삼.

$res = mysql_query("SELECT * FROM People"); // add WHERE clauses if needed 
$names = array(); 
$parents = array(); 
$children = array(); 

while ($row = mysql_fetch_object($res)) { 
    $names[ $row->id ] = array($row->firstname, $row->lastname); 
    if ($row->parent == 0) { 
     $parents[] = $row->id; 
    } else { 
     if (!array_key_exists($row->parent, $children)) 
      $children[ $row->parent ] = array(); 
     $children[ $row->parent ][] = $row->id; 
    } 
} 

foreach ($parents as $parent_id) { 
    // print parent header 
    if (array_key_exists($parent_id, $children)) { 
     foreach ($children[ $parent_id ] as $child_id) { 
      // print child row 
     } 
    } 
} 

시를 : 세 번째 옵션은 단순한 SELECT * FROM People 쿼리의 모든 행을 가져오고 PHP에서 트리를 구축하는 것입니다. 실제로 을 모두의 테이블에있는 부모와 자식으로 나타내지 않고 단일 패밀리에 속한 자식 만 표시하려면 너무 많은 레코드를 가져 오지 않도록 SQL에서 필터링을 시도해야합니다.

0

왜 JavaScript로 다중 선형 배열을 만들지 않습니까? 그런 다음 배열을 반복하여 DOM에서 결과를 얻으십시오.

$res = mysql_query("SELECT PARENT"); 
while($row = mysql_fetch_assoc($res)) 
{ 

    // echo parent 

    $res2 = mysql_query("SELECT CHILD WHERE PARENT SOMETHING"); 
    while($row2 = mysql_fetch_assoc($res2)) 
    { 

    // echo child 
    } 
} 

를 또는 나중에 그것을 유지하고, 플래그를 저장 :

+1

웹 사이트 사용자는 Javascript를 사용할 필요가 없어야하기 때문에. Javascript로 DOM을 조작하지 않고 부모 -> 어린이 관계 목록을 표시 할 수없는 이유는 무엇입니까? PHP와 MySQL을 사용하고 있습니다. –

1

당신은 루프에서 루프를 사용할 수 있습니다.

$people = array(); 

$res = mysql_query("SELECT PARENT"); 
while($row = mysql_fetch_assoc($res)) 
{ 
    $people[] = array('is_parent' => true, 
        'info'  => $row); 

    $res2 = mysql_query("SELECT CHILD WHERE PARENT SOMETHING"); 
    while($row2 = mysql_fetch_assoc($res2)) 
    {  
    $people[] = array('is_parent' => false, 
         'info'  => $row2); 
    } 
} 

// later 

foreach($people as $person) 
{ 
    if($person['is_parent']) 
    { 
    // echo parent 
    } 
    else 
    { 
    // echo child 
    } 
} 
+0

물론 가능 하겠지만, 제 질문에서 언급했듯이, 그렇게하면 테이블이 커짐에 따라 성능에 문제가 발생할 수 있습니다. –

2

전통적인 접근 방법에 따르면, SQL을 시작으로 테이블을 조인한다고 생각합니다 (이 경우 왼쪽 테이블과 오른쪽 테이블이 같을지라도) 좋은 출발점이 될 수 있습니다.

이것은 주로 RDBMS를 사용하기 때문에 항상 테이블 형식 구조를 처리하고 데이터 일관성에 대해 보장되는 방식으로 테이블을 조인해야하기 때문입니다.

그래서, 같은 시작 :

SELECT 
     a.id parent_id, a.firstname parent_name, a.lastname parent_lastname, 
     b.id child_id, b.firstname child_firstname, b.lastname child_lastname 
FROM 
     People a LEFT OUTER JOIN People b ON a.id = b.parent 
WHERE 
     a.parent = 0; 

둘째, 어떤을 줄 것이다, 당신은 "fetch_all"전략을 사용하고 선호한다 (예를 들어, mysqli PHP 확장으로뿐만 아니라 PDO 사용할 수 있습니다) 하나의 단일 연산으로 전체 결과 세트를 2 차원 연관 배열로 가져올 수 있습니다.

이 시점에서 경로를 선택할 수 있습니다.

All-PHP : PHP로 배열을 걸러서 프리젠 테이션 마크 업을 직접 구축하여 필요에 따라 구성된 데이터를 표시 할 수 있습니다. echo 브라우저쪽으로 html 문자열 보내기.

AJAX : 예를 들어 PHP 스크립트가 AJAX를 통해 호출되었지만 쿼리 결과 배열을 걸을 수도 있지만 이번에는 호출에 응답 할 JSON 구조를 구현하기 위해 해석합니다. 그렇게 : 완벽하게 인식하고 걸을 수있는 자바 스크립트 클라이언트 측이 기존의 빈 테이블 골격을 채울 수 있기 때문에

{ 
    "1": { 
     "id": 1, 
     "firstname": "James", 
     "lastname": "Donovan", 
     "children": { 
      "6": { 
       "id": 6, 
       "firstname": "Nikolai", 
       "lastname": "Donovan" 
      } 
     } 
    }, 
    "2": { 
     "id": 2, 
     "firstname": "Jeffrey", 
     "lastname": "Williams", 
     "children": { 
      "4": { 
       "id": 4, 
       "firstname": "Carol", 
       "lastname": "Williams" 
      }, 
      "5": { 
       "id": 5, 
       "firstname": "Sarah", 
       "lastname": "Williams" 
      } 
     } 
    }, 
    "3": { 
     "id": 3, 
     "firstname": "Emmit", 
     "lastname": "Herring", 
     "children": { } 
    } 
} 

이러한 표현은, 데이터 교환을위한 더 나은 것입니다. 물론 당신은 json_encode()에 결과 배열을이 같은 다른 것으로 재구성하는 대신 직접 배열을 가질 수 있습니다. 그러나 당신은 이미 가지고있는 솔리드 레코드 셋 배열 표현보다 훨씬 더 멀리 가지 않을 것이라고 생각할 것입니다.

마지막으로, all-mysql 솔루션은 사용자가 찾고있는 데이터 구조를 의도적으로 생성하는 저장 프로 시저를 준비하는 것입니다. 첫 번째 열에 학부모의 전체 이름과 후속 열로 어린이의 전체 이름 (Emmit Herring과 같이 자녀가없는 경우 빈 필드)을 갖는 가족 당 1 행.

PHP로 결과 세트를 다시 "fetch_all"할 수 있으며, 배열을 따라 가면 완료됩니다.

성능에 문제가있는 경우,이 마지막 접근 방식은 컴퓨팅로드 및 메모리 사용면에서 서버에서 가격을 지불해야한다고하더라도 반드시 최상의 결과를 보장해야합니다. 엄청난 양의 데이터를 다룰 수 있습니다.

관련 문제