0

我已经建立了一些产品数据库,但我从未对数据库的效率感到真正满意。我最好的方法是有一个产品表、一个类别表和一个关系表,即:

产品表:

id    product_name     data
1     Some prod        More info...
2     Another prod     Even more...

类别表:

id    parent_id   cat_name
1     0           Main cat 1
2     1           Sub cat 1
3     1           Sub cat 2
4     3           Sub sub cat 1
5     0           Main cat 2

关系表:

id    prod_id    cat_id
1     1          2
2     1          4
3     2          5
etcetera...

这样可以快速轻松地检索产品,也可以轻松地将一种产品分配给多个类别。

然而,创建类别列表的结构并不像我想的那么简单。首先,我需要循环主类别,然后相应地循环所有子级别。我只喜欢显示分配了产品的类别,但是如果子级别包含产品,我当然还需要显示所有父类别。这导致大量查询、连接和条件例程来呈现当前类别。我想知道是否有更有效的结构方法来解决这个问题?你不需要写我的代码我只是想知道可能有什么样的更好的原则?

4

2 回答 2

2

典型的递归方法是邻接表和多对多表。

典型的非递归方法是多对多祖先表和嵌套集

邻接列表是那些包含“parent_id”引用的结构。

递归读取多对多表是您的方法。

祖先表是多对多表,但它们也包含子-祖父连接并指定每个连接的级别。它们提供最大的灵活性和最快的读/写速度。

嵌套集是一种非常不同的方法,它们只允许严格的树结构而不是图。它们的写入成本也更高,但读取非常容易。

同样关于嵌套集,手动维护结构非常困难。您需要实现几个函数并选择何时使用每个函数,因为在子列表末尾插入一个节点需要一个函数 ( appendNodeTo($parentNode)),而在子列表中间插入一个节点需要另一个函数。移动节点取决于天气,节点是终端节点(叶子),或者它是否具有具有特定功能的子节点(分支)。

于 2012-09-10T08:10:17.893 回答
1

这不是最有效的方法,但这样你只需要 1 个 sql 请求(查询)

 public function get_menu_data()
    {
        $result = mysql_query(" 
            SELECT 
                id, parent, name 
            FROM 
                category 
            ORDER BY 
                parent, name 
        "); 
        //$cat = $this->db->get("category");
        $menuData = array( 
            'items' => array(), 
            'parents' => array() 
        ); 

        while ($menuItem = mysql_fetch_assoc($result)) 
        { 
           $menuData['items'][$menuItem['id']] = $menuItem; 
           $menuData['parents'][$menuItem['parent']][] = $menuItem['id']; 
        } 
        return $menuData;

    }

function buildMenu($parentId, $menuData)
{
    $html = '';
    if (isset($menuData['parents'][$parentId]))
    {
        $html = '<ul>';
        foreach ($menuData['parents'][$parentId] as $itemId)
        {
            $html .= '<li>' . $menuData['items'][$itemId]['name'];
            // find childitems recursively
            $html .= $this -> buildMenu($itemId, $menuData);
            $html .= '</li>';
        }
        $html .= '</ul>';
    }
    return $html;
}

称之为:显示所有类别:

buildMenu(0,get_menu_data());

显示类别 1 的子类别:

buildMenu(1,get_menu_data());

祝你好运,我希望这段代码对你有帮助

于 2012-09-10T08:14:38.833 回答