例如,“Dole Banana”是一种产品,它列在“香蕉”类别下,当我打开“Fruit”类别时,我想看到“Dole Banana”。
+ Food
|--+ Fruits
|------+ Bananas
|------+ Apples
|--+ Vegetables
|------+ Onion
|------+ Spinach
答案 0 :(得分:3)
如果您正在寻找解决此问题的在线资源,“在数据库中存储树”将是一个很好的搜索短语。
至于解决方案,请注意每个子类别可以包含一个或零个父类别。因此,整个树可以存储在具有“父”字段的单个自引用表中。
使用示例树:
ID | PARENT | NAME
-----+--------+-------------
1 | null | Food
2 | 1 | Fruits
3 | 2 | Bananas
4 | 2 | Apples
5 | 1 | Vegetables
6 | 5 | Onion
7 | 5 | Spinach
答案 1 :(得分:3)
我通常使用left-right trees,它们非常适合数据库查询。每个节点都有一个parentId,left和right值。每个节点子节点具有左/右值,该值在左和右父节点之间,这使得很容易找到例如节点的所有子节点/父节点。它确实会给插入带来轻微的开销,但除非你插入很多,否则不应该产生太大的影响。
编辑:只是一句警告,你需要在锁定的事务中进行插入/更新操作,否则树会搞乱。
答案 2 :(得分:1)
包含3个字段的表“类别”。
获取所有根类别
select * from Categories where ParentCategoryId is null
获取某些特定类别的所有子类别:
select * from Categories where ParentCategoryId = 12
答案 3 :(得分:0)
您可以使用带有parent_category_id的简单表结构,并使用递归检索整个树或实现左/右值,并使用预先排序的树遍历方法获取整个树。
答案 4 :(得分:0)
如果您指的是无限多个级别,那么可以递归的自引用表。示例:StuffID,StuffName,StuffParentID(FK到Stuff ID)
对于有限数,固定表:父子孙子
答案 5 :(得分:0)
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
答案 6 :(得分:0)
对于无限层次结构,请使用modified preorder tree traversal algorithm
答案 7 :(得分:0)
这是一种可能对您有用的不同方法。它的维护成本略高于PARENT_ID或lft / rght方法,但检索更容易(也更快)。
多尔香蕉可以在产品表中。您有一个产品的category_id。我们要求允许产品的多个类别。这导致我们有一个categories_products连接表,其中产品可以有多个连接的行。然后,我们必须决定是否只在香蕉,香蕉及其所有父母中都有多尔香蕉。由于检索速度至关重要,我们将dole香蕉放在其类别及其所有父类别中。 dole香蕉有三种类别 - 产品连接。
使用此结构,返回任何类别的所有项目既简单又快捷,只需一个查询。您不能在PARENT_ID方法中执行此操作(除非您对父母,祖父母等进行硬编码)。添加类别很容易。对产品进行分类需要在连接表中插入多行。删除和移动类别有点棘手。