2011-05-12 18 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表店是属于哪一类。一个项目可以属于顶级和/或子类别。大约有3个深度类别,即Tob级别,子级别和子级别。

用户选择他们想要查看并提交类别的,我可以用下面的示例查询查询数据库..

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

这工作得很好。

我的问题是,是否可以查看所有的下一个顶级类的项目,即使它没有被直接分配到项目。例如,如果用户选择上述家具,然后它会列出所有项目属于它的子类(即使ItemCategory不包含任何记录)?

我愿意作出必要amendements的数据表或疑问,请提出一个解决方案。谢谢。

+0

你想要一个纯粹的MySQL解决方案,还是PHP/MySQL解决方案就足够了? – GordyD 2011-05-12 15:25:19

+0

php和mysql更适合我,我会说。 thx – Kay 2011-05-12 16:06:59

回答

1

看守给了一个很好的答案,但我会有些改变我的做法为以下,所以你必须使用类别为键和项目为值的结构化递归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 2011-05-12 16:17:06

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,以及该项目的分配类别编号,项目名称等

+0

嗯..我想过这个,但因为我有一个复杂的查询需要看看它是如何适合.. thx为你的答案。 – Kay 2011-05-12 16:11:14

0

如果你使用MySQL,你”每个二级数组元素重新运气出短使用典型技术,这通常意味着预先计算并存储的路径,或使用嵌套集合索引您的树:

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

如果可以切换到PostgreSQL,可以替代地使用递归查询:

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

显然,你也可以从递归您的应用程序查询,但它是少了很多有效的。

+0

嗯..我想我已经试过嵌套集模型之前,这是一个痛苦,维护.. thx为你的输入 – Kay 2011-05-12 16:05:35

+0

是的,它是慢写入,如果使用。如果你放弃(rgt - lft - 1)/ 2产生孩子并使用浮标,它会快得多(但仍然是一个难以维持的)。 – 2011-05-12 16:07:46

相关问题