我应该为站点使用什么样的数据库结构具有无限的子类别?

时间:2009-09-13 16:37:26

标签: sql database-design data-modeling hierarchical-data

例如,“Dole Banana”是一种产品,它列在“香蕉”类别下,当我打开“Fruit”类别时,我想看到“Dole Banana”。

+ Food
|--+ Fruits
|------+ Bananas   
|------+ Apples
|--+ Vegetables
|------+ Onion
|------+ Spinach

8 个答案:

答案 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个字段的表“类别”。

  1. CategoryId not null(主键)
  2. ParentCategoryId null
  3. CategoryName not null
  4. 获取所有根类别

    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方法中执行此操作(除非您对父母,祖父母等进行硬编码)。添加类别很容易。对产品进行分类需要在连接表中插入多行。删除和移动类别有点棘手。