2011-05-12 3 views
2

데이터 테이블을 참조하고 아래 질의하시기 바랍니다 ..최상위 카테고리를 선택하여 하위 카테고리에 속한 항목을 검색하려면 어떻게해야합니까?

Items 
Id, Name 
1, Item 1 
2, Item 2 

Categories 
Id, Name, Parent ID 
1, Furniture , 0 
2, Tables, 1 
3, Beds, 1 
4, Dining Table, 2 
5, Bar Table, 2 
4, Electronics, 0 
5, Home, 4 
6, Outdoors, 4 
7, Table lamp, 4 

ItemCategory 
ItemId, CategoryId 
1, 2 .. Row1 
2, 4 .. Row 2 
2, 5 .. Row 3 

ItemCategory 테이블에는 항목은 범주에 속한다. 항목은 최상위 및 하위 범주에 속할 수 있습니다. Tob 수준, 하위 수준 및 하위 하위 수준이라는 약 3 가지 수준의 범주가 있습니다.

사용자는보고 제출하고자하는 모든 범주를 선택하고 난

SELECT * FROM items i INNER JOIN ItemCategory ic ON 
ic.itemId = i.itemId AND ic.itemId IN ('comma separated category ids') 

이 잘 작동 .. 아래 샘플 쿼리를 사용하여 데이터베이스를 조회 할 수 있습니다.

내 질문은 항목에 직접 할당되지 않은 경우에도 최상위 카테고리 아래의 모든 항목을 볼 수 있습니까? 예를 들어 사용자가 위의 가구를 선택한 경우 하위 카테고리에 속한 모든 항목이 나열됩니다 (ItemCategory에는 레코드가 없습니다)?

데이터 테이블이나 쿼리에 필요한 수정안을 작성하는 데 열어 두었습니다. 해결책을 제안하십시오. 고맙습니다. 재귀와

+0

순수 MySQL 솔루션을 원하십니까, 아니면 PHP/MySQL 솔루션으로 충분합니까? – GordyD

+0

PHP와 MySQL은 내가 더 잘 적응할 수 있다고 말한다. thx – Kay

답변

1

Watcher는 좋은 대답을주었습니다.하지만 접근 방법을 다음과 같이 약간 변경 했으므로 범주로 키와 항목을 값으로 갖는 구조화 된 재귀 2 차원 배열이 있습니다. 따라서 검색 요구 사항에 응답 할 때 사용자에게 다시 인쇄하는 것이 매우 쉽습니다. 이 도움이

$items = getItemsByCategory($topCategory); 
//To print contents 
print_r($items); 

function getItemsByCategory($sid = 0) { 
    $list = array(); 
    $sql = "SELECT Id, Name FROM Categories WHERE ParentId = $sid"; 
    $rs = mysql_query($sql); 
    while ($obj = mysql_fetch_object($rs)) { 
    //echo $obj->id .", ".$parent." >> ".$obj->name."<br/>"; 
    $list[$obj->name] = getItems($obj->id); 
    if (hasChildren($obj->id)) { 
     array_push($list[$obj->name],getItemsByCategory($obj->id)); 
    } 
    } 
    return $list; 
} 

function getItems($cid) { 
    $list = array(); 
    $sql = "SELECT i.Id, i.Name FROM Items p INNER JOIN ItemCategory ic ON i.id = ic.ItemId WHERE ic.CategoryId = $cid"; 
    $rs = mysql_query($sql); 
    while ($obj = mysql_fetch_object($rs)) { 
    $list[] = array($obj->id, $obj->name); 
    } 
    return $list; 
} 

function hasChildren($pid) { 
    $sql = "SELECT * FROM Categories WHERE ParentId = $pid"; 
    $rs = mysql_query($sql); 
    if (mysql_num_rows($rs) > 0) { 
    return true; 
    } else { 
    return false; 
    } 
} 

희망 : 여기

내가 테스트 한 나의 접근 방식이다.

+0

감사합니다. – Kay

1

, 아무것도 가능하다 :

function fetchItemsByCat($cat, &$results) { 
    $itemsInCat = query("SELECT Items.Id FROM Items INNER JOIN ItemCategory ON ItemCategory.ItemId = Items.Id WHERE CategoryId = ?", array($cat)); 

    while($row = *_fetch_array($itemsInCat)) 
     array_push($results, $row['Id']); 

    $subCategories = query("SELECT Id FROM Categories WHERE Parent = ?", array($cat)); 
    while($row = *_fetch_array($subCategories)) 
     $results = fetchItemsByCat($row['Id'], $results); 

    return $results; 
} 

$startCat = 1; // Furniture 

$itemsInCat = fetchItemsByCat($startCat, array()); 

기능은 다소 의사 코드입니다. *_fetch_array을 사용중인 데이터베이스 확장자로 바꿉니다. 그러나 쿼리 함수는 데이터베이스를 쿼리합니다.

또한 테스트되지 않았으므로 배열 참조를 사용하여 예기치 않은 결과가 있는지 테스트해야합니다.

$itemsInCat은 주어진 시작 범주에있는 모든 항목/하위 항목의 정수 ID 배열입니다. 만약 당신이 궁금해지기를 원한다면, 아이템 ID를 가진 각 2 레벨 배열 요소와 그 아이템의 할당 된 카테고리 아이디, 아이템 이름 등과 같은 배열 배열을 반환 할 수 있습니다.

+0

흠 .. 나는 이것에 대해 생각해 봤지만 복잡한 쿼리는 어떻게해야할까요? – Kay

0

MySQL을 사용한다면, 일반적으로 미리 계산하고 경로를 저장, 또는 중첩 세트를 사용하는 것을 의미 일반적인 기술을 사용하여 트리 색인의 짧은 운이 다시 : 당신은 PostgreSQL을 전환 할 수있는 경우

http://en.wikipedia.org/wiki/Nested_set_model

을, 당신은 대안을 사용할 수 있습니다 재귀 쿼리 :

http://www.postgresql.org/docs/9.0/static/queries-with.html

분명히 앱에서 재귀 적으로 쿼리 할 수도 있지만 효율성은 훨씬 떨어집니다.

+0

흠 .. 전에는 중첩 된 모델을 시도한 것 같아요. 유지하기가 힘들었습니다. ur 입력에 대해 쓰다. – Kay

+0

그래, 사용하는 경우 글쓰기가 느려요. 당신이 (rgt-lft-1)/2를 떨어 뜨리면 아이들이 생기고 대신에 수레를 사용하면 훨씬 빠릅니다 (그러나 여전히 유지하기가 쉽지 않습니다). –

관련 문제