0

私はいくつかの製品データベースを構築しましたが、データベースの効率に本当に満足することはありません。これまでの私の最善のアプローチは、1つの製品テーブル、1つのカテゴリテーブル、次に1つの関係テーブルを用意することです。

製品表:

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...

これにより、製品をすばやく簡単に取得でき、1つの製品を複数のカテゴリに簡単に割り当てることができます。

ただし、カテゴリリストを作成するための構造は、私が望むほど単純ではありません。最初にメインカテゴリをループし、次にすべてのサブレベルをループする必要があります。製品が割り当てられているカテゴリのみを表示するのが好きですが、もちろん、サブレベルに製品が含まれている場合は、すべての親カテゴリも表示する必要があります。これにより、現在のカテゴリを表示するためのクエリ、結合、および条件付きルーチンが多数生成されます。この問題に対してより効率的な構造的アプローチがあるのではないかと思います。あなたは私のコードを書く必要はありません私はただどんな種類のより良い原則があるのだろうかと思いますか?

4

2 に答える 2

2

典型的な再帰的アプローチは、隣接テーブルと多対多テーブルです。

典型的な非再帰的アプローチは、多対多の祖先テーブルとネストされたセットです。

補助リストは、「parent_id」参照を含む構造です。

再帰的に読み取られる多対多のテーブルがあなたのアプローチです。

祖先テーブルは多対多のテーブルですが、子と祖父の接続も含まれ、各接続のレベルを指定します。それらは、最大の柔軟性と最速の読み取り/書き込み速度を可能にします。

ネストされたセットは非常に異なるアプローチであり、グラフではなく厳密なツリー構造のみを許可します。また、書き込みにはコストがかかりますが、読み取りには非常に簡単です。

ネストされたセットに関しても、構造を手動で維持することはかなり困難です。appendNodeTo($parentNode)また、子リストの最後にノードを挿入するには1つの関数( )が必要であり、子リストの中央にノードを挿入するには別の関数()が必要なため、いくつかの関数を実装し、それぞれをいつ使用するかを選択する必要があります。ノードの移動は、天候に応じて、ノードがターミナルノード(リーフ)であるか、またはそのための特定の機能を備えたサブノード(ブランチ)があるかどうかによって異なります。

于 2012-09-10T08:10:17.893 に答える
1

これは最も効率的な方法ではありませんが、この方法で必要なSQLリクエスト(クエリ)は1つだけです。

 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 に答える