親 ID を取得したい場合:
だからあなたが与えられたと仮定してください
set @parentId = 1 /*toys*/
select
*
from
Items i
inner join Categories c on c.id = i.categoryId
where
c.parentId = @parentId
これにより、必要な項目が得られますが、大きな設計上の欠陥が 1 つあります。それは、複数レベルの階層カテゴリを処理できないことです。
次の Categories テーブルがあるとします。
*Categories table*
id | name | parentId
1 | Toys | 0
2 | Dolls | 1
3 | Bikes | 1
4 | Models | 2
5 | Act.Fig.| 2
6 | Mountain| 3
7 | BMX | 3
そしてアイテム:
*items table*
item | category_id
Barbie | 4
GIJoe | 5
Schwinn| 6
Huffy | 7
関連するすべてのアイテムを取得する唯一の方法は、自己結合を行うことです。
select
*
from
Items i
inner join Categories c on c.id = i.categoryId
inner join Categories c2 on c.parentId = c2.id
where
c2.parentId = @parentId
複数レベルの階層を持つことができるため、このパターンはスケーラブルではありません。
階層を処理する一般的な方法の 1 つは、「フラット化された」テーブルを作成することです。つまり、各ノードをそのすべての子孫にリンクする行です。
Categories テーブルに加えて、2 つ目のテーブルを作成します。
*CategoriesFlat table* The Name column is here only for readability
id | name | parentId
1 | Toys | 1
-----------------
2 | Dolls | 1
2 | Dolls | 2
-----------------
4 | Models | 1
4 | Models | 2
4 | Models | 4
5 | Act.Fig.| 1
5 | Act.Fig.| 2
5 | Act.Fig.| 5
-----------------
3 | Bikes | 1
3 | Bikes | 3
-----------------
6 | Mountain| 1
6 | Mountain| 3
6 | Mountain| 6
7 | BMX | 1
7 | BMX | 3
7 | BMX | 7
したがって、次のように書くことができます。
select
*
from
Items i
inner join CategoriesFlat c on c.id = i.categoryId
where
c.parentId = @parentId
そして、関連するすべてのカテゴリとアイテムを取得します。
これは、SQL のアンチパターンとその解決策に関する素晴らしいスライドショーです。(SQL の階層データはアンチパターンですが、がっかりしないでください。誰もがこのパターンに遭遇します)