たとえば、「ドールバナナ」は一種の商品で、「バナナ」のカテゴリに表示されますが、「果物」のカテゴリを開くと、「ドールバナナ」が表示されます。
+ Food
|--+ Fruits
|------+ Bananas
|------+ Apples
|--+ Vegetables
|------+ Onion
|------+ Spinach
たとえば、「ドールバナナ」は一種の商品で、「バナナ」のカテゴリに表示されますが、「果物」のカテゴリを開くと、「ドールバナナ」が表示されます。
+ Food
|--+ Fruits
|------+ Bananas
|------+ Apples
|--+ Vegetables
|------+ Onion
|------+ Spinach
この問題に対処するオンラインリソースを探している場合は、「データベースにツリーを保存する」が適切な検索フレーズになります。
解決策として、各サブカテゴリは1つまたは0の親カテゴリを持つことができることに注意してください。したがって、ツリー全体を「親」フィールドを持つ単一の自己参照テーブルに格納できます。
サンプルツリーの使用:
ID | PARENT | NAME
-----+--------+-------------
1 | null | Food
2 | 1 | Fruits
3 | 2 | Bananas
4 | 2 | Apples
5 | 1 | Vegetables
6 | 5 | Onion
7 | 5 | Spinach
私は通常、データベースクエリに非常によく適合した左右のツリーを使用しました。各ノードには、parentId、leftおよびrightの値があります。すべてのノードの子には、親ノードの左右の間にある左/右の値があります。これにより、たとえば、ノードのすべての子/親を簡単に見つけることができます。挿入にわずかなオーバーヘッドが発生しますが、大量に挿入しない限り、それほど大きな影響はありません。
編集:警告の言葉ですが、ロックされたトランザクションで挿入/更新操作を行う必要があります。そうしないと、ツリーが台無しになる可能性があります。
3つのフィールドを持つテーブル「カテゴリ」。
すべてのルートカテゴリを取得するには
select * from Categories where ParentCategoryId is null
特定のカテゴリのすべてのサブカテゴリを取得するには:
select * from Categories where ParentCategoryId = 12
parent_category_idを使用して単純なテーブル構造を使用し、再帰を使用してツリー全体を取得するか、左/右の値を実装して、事前に順序付けられたツリートラバーサルメソッドを使用してツリー全体をフェッチできます。
レベルの数が無限であることを意味する場合は、再帰できる自己参照テーブル。例:StuffID、StuffName、StuffParentID(FKからStuff ID)
有限数の場合、固定テーブル:親-子-孫
CREATE TABLE [dbo].[Category](
[CategoryId] [int] NOT NULL,
[ParentCategoryId] [int] NULL,
[CategoryName] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Category] PRIMARY KEY CLUSTERED
(
[CategoryId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON
[PRIMARY]
GO
ALTER TABLE [dbo].[Category] WITH CHECK ADD CONSTRAINT [FK_Category_Category] FOREIGN KEY([ParentCategoryId])
REFERENCES [dbo].[Category] ([CategoryId])
GO
ALTER TABLE [dbo].[Category] CHECK CONSTRAINT [FK_Category_Category]
GO
無限階層の場合は、変更されたプレオーダーツリートラバーサルアルゴリズムを使用します
これがあなたに役立つかもしれない別のアプローチです。PARENT_IDまたはlft/rghtアプローチよりもわずかに多くの保守コストがかかりますが、取得ははるかに簡単です(そして高速です)。
ドールバナナは製品テーブルに入れることができます。商品のcategory_idは1つです。
1つの商品に複数のカテゴリを許可する必要がありました。これにより、categories_products結合テーブルが作成され、productには複数の結合行が含まれる可能性があります。次に、ドールバナナをバナナだけに入れるか、バナナとそのすべての親に入れるかを決定する必要がありました。検索の速度が重要であるため、ドールバナナをそのカテゴリとそのすべての親カテゴリに分類しました。ドールバナナには3つのカテゴリ製品結合があります。
この構造を使用すると、任意のカテゴリからすべてのアイテムを簡単かつ迅速に返すことができ、クエリは1つだけです。PARENT_IDアプローチでは、これを行うことはできません(親、祖父母などをハードコーディングしない限り)。カテゴリの追加は簡単です。製品を分類するには、結合テーブルに複数の行を挿入する必要があります。カテゴリの削除と移動は少し注意が必要です。