6

カテゴリー運営をしています。各行にparentIdがある場所。カテゴリは n レベルにすることができます。カテゴリ ツリー配列を返す php 関数を再帰的に呼び出すことができます。

ここに画像の説明を入力

現在の問題は次のとおりです。管理パネルで、以下に示すようにカテゴリ一覧ページが必要です。つまり、どのカテゴリがどの下にあるか。

  • 商品 (編集) (削除)
  • 製品 > 製品 1 (編集) (削除)
  • 製品 > 製品 2 (編集) (削除)
  • 製品 > 製品 2 > 製品 2 1 (編集) (削除)
  • 製品 > 製品 2 > 製品 2 2 (編集) (削除)
  • お問い合わせ (編集) (削除)

上記と同じ順序でmysqlクエリの結果が必要です。どうすればそれを達成できるかわかりません。

SELECT *
FROM tbl_categories
ORDER BY ???

ガイドしてください。

4

3 に答える 3

2

このテーブル構造に基づいて期待どおりに並べられた結果をもたらす単一の SQL クエリはありません。

この問題を解決するには、次の 2 つの方法があります。

  1. 外部アプリケーション ロジック (DB の外部) を使用して、各カテゴリの子を検出し、アプリケーションでツリーを構築する再帰呼び出しを行います。

  2. リレーショナル データベースにツリー データを格納するためのアルゴリズムの 1 つを使用します。そのようなアルゴリズムの 1 つは、Modified Preorder Tree Traversalまたは単に MPTT と呼ばれます。

lft列を使用し、トラバーサルで左/右のインデックスを維持すると仮定するとrgt、新しいカテゴリを挿入するときに次のことが必要になります。

  1. Id で親カテゴリ情報を取得:SELECT lft,rgt FROM tbl_categories WHERE categoryId=5 例として、親カテゴリがlft=7あり、rgt=10(この場合は既に 1 つの子がある)と仮定します。

  2. 新しいエントリのためのスペースを作ります - すべてのレコードを 2 シフトします (lft の場合は 1、rgt の場合は 1):

    UPDATE tbl_categories SET rgt=rgt+2 WHERE rgt>=10 ORDER BY rgt DESC

    UPDATE tbl_categories SET lft=lft+2 WHERE lft>=10 ORDER BY lft DESC

ここでORDER下降に注意してください。とは一意であるlftrgt想定されているため、それらに制約を設定することをお勧めしUNIQUEます。次に、重複キー エラーを防ぐために、更新の降順が必要です。

  1. 新しいレコードを設定lft=<former parent rgt>rgt=<former parent rgt +1>て挿入...

    INSERT INTO tbl_categories SET categoryName="New Child",parentCategoryId=5,lft=11,rgt=12,...

を検索すると、コード付きのより詳細な例を見つけることができますMPTT PHP MySQL。このテーマに関するチュートリアルはかなりあります。

于 2012-07-12T09:49:27.563 に答える
2

ルート パスを再帰的に取得し、親と連結するストアド関数を使用できます。

DELIMITER $$
DROP FUNCTION IF EXISTS `get_category`$$
CREATE FUNCTION `get_category`(cat_id int) RETURNS VARCHAR(255)
READS SQL DATA
BEGIN
DECLARE c_id INT;
DECLARE p_id INT;
DECLARE count INT;
DECLARE cat_name VARCHAR(255);
DECLARE cat_path VARCHAR(255);
set c_id = cat_id;
SELECT parent_category_id, category_name INTO p_id, cat_name FROM categories WHERE category_id = c_id;
set c_id = p_id;
set cat_path=cat_name;
set count=0;
WHILE (c_id IS NOT NULL) DO 

SELECT parent_category_id, category_name INTO p_id, cat_name FROM categories WHERE category_id = c_id;
set c_id = p_id;
set cat_path = concat_ws('>',cat_name,cat_path);
set count = count + 1;
IF count=10 THEN
  SET c_id = NULL;
END IF;
 END WHILE;
RETURN cat_path;
END
$$
DELIMITER ;

を使用して呼び出します

select getcategory(category_id);

この関数では、無限ループを回避するために健全性チェックを行いました..

于 2012-07-12T10:01:44.900 に答える
0

単一の mysql クエリでこれを達成することはできません。複数のクエリを実行することで、これを実現できます。アルゴリズムは次のようになります。最初に、データベースからデータを取得することにより、入力するデータ セット オブジェクトを作成します。親 ID をパラメーターとして取り、存在する場合は子ノードを返し、子がない場合は -1 を返すメソッドを作成します。ステップ 1: 親 (ルート) ノードを持たないすべての行をフェッチします。Step2: この結果を繰り返します。たとえば、結果セットで prod1 と prod2 が最初に返されたノードである場合。この RS を反復して prod1 を取得し、DataSET obj に行を挿入します。次に、prod1 の ID を getCHILD メソッドに送信してその子を取得し、返された結果セットを繰り返して、最下位のノードが取得されなくなるまで getCHILD メソッドを呼び出します。

于 2012-07-12T09:42:17.617 に答える