请参阅下面的数据表和查询..
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不包含任何记录)?
我愿意对数据表或查询进行必要的修改,请提出解决方案。谢谢。
答案 0 :(得分: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,以及该项目分配的类别ID,项目名称等。
答案 1 :(得分:1)
Watcher已经给出了一个很好的答案,但是我在某种程度上改变了我的方法,所以你有一个结构化的递归二维数组,其中类别为键,项目为值。这使得在响应搜索要求时可以非常轻松地打印回用户。
这是我的方法,我测试过:
$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;
}
}
希望这有帮助。
答案 2 :(得分:0)
如果您使用MySQL,那么使用典型技术索引您的树是不吉利的,这通常意味着预先计算和存储路径,或者使用嵌套集:
http://en.wikipedia.org/wiki/Nested_set_model
如果您可以切换到PostgreSQL,您也可以使用递归查询:
http://www.postgresql.org/docs/9.0/static/queries-with.html
显然,您也可以从您的应用程序递归查询,但效率低得多。