1

我有以下数据库结构:

[CATEGORY]
category_id
parent(default 0)
title

[PRODUCT]
product_id
title

[PRODUCT_TO_CATEGORY]
product_id
category_id

CATEGORY的样本数据:

1   0   TV
2   1   PLASMA
3   1   LED
.   .   ...

产品样本数据:

1   Sony
2   Sharp
3   Samsung
.   ...

PRODUCT_TO_CATEGORY的示例数据:

1(Sony)    1(TV)
2(Sharp)   2(PLASMA)
3(Samsung) 2(PLASMA)

首先我想问一下我的结构好不好。例如,我应该为每个产品分配类别和子类别 ID,还是单个类别效果好?

然后基于每个产品属于一个类别并且一个类别可能有一个或多个父类别的假设,我如何检索当前和每个子类别的产品?
例如,点击电视类别应列出索尼、夏普和三星,而不仅仅是索尼项目。

4

2 回答 2

1

父级(默认 0)

使用 NULL 而不是 0。这将允许您使用正确的 FOREIGN KEY(如下图所示)。


我应该为每个产品分配类别和子类别 ID

你不应该。只需分配适用于该产品的最具体的子类别。所有超类别都可以从CATEGORY表中定义的层次结构中推断出来,因此将它们(甚至其中之一)存储在产品中是多余的。

出于性能原因,有时可以证明这种冗余是合理的,但是您必须在它们与数据一致性之间取得平衡。在这种情况下,没有很好的声明方式来保持冗余数据与“主”数据同步——你必须通过触发器或(上帝保佑)应用程序代码来做到这一点,这样做可能会引入并发错误,除非您非常非常仔细地考虑您的锁定策略。


然后基于每个产品属于一个类别的假设......

这种假设使您的模型不正确。要正确建模这种 N:1 关系,您不需要联结表PRODUCT_TO_CATEGORY,您只需要产品和类别之间的外键:

在此处输入图像描述

注意:PRODUCT.CATEGORY_ID如果您想允许无类别产品(即您的关系实际上是 N:0..1 而不是 N:1),请使 NULL-able。

你的数据看起来像:

CATEGORY:

1   TV      NULL
2   PLASMA  1
3   LED     1

PRODUCT:

1   Sony    1 (TV)
2   Sharp   2 (PLASMA)
3   Samsung 2 (PLASMA)

如何检索当前和每个子类别的产品?

首先识别属于所需“子树”的所有类别,然后检索连接到它们的产品。在这种情况下,搜索所有电视可以这样完成:

  1. 获取您正在搜索的“顶级”类别的 ID:1(电视)。

    SELECT CATEGORY_ID FROM CATEGORY WHERE TITLE = 'TV'

  2. 获取所有子类别的 ID:2 (PLASMA) 和 3 (LED)。

    SELECT CATEGORY_ID FROM CATEGORY WHERE PARENT_ID IN (1)

  3. 重复步骤 (2),直到到达层次结构的“底部”:

    SELECT CATEGORY_ID FROM CATEGORY WHERE PARENT_ID IN (2, 3)

    上面的查询将为您的示例数据返回一个空结果集,因此您知道可以停止。在更精细的层次结构中,您可能需要多次重复上述查询,始终将 IN 列表替换为最近检索到的类别“层”。

    如果您的数据碰巧有一个循环,请注意无限迭代!

  4. 将所有产品连接到任何已识别的类别:1 (TV)、2 (PLASMA) 和 3 (LED)。

    SELECT * FROM PRODUCT WHERE CATEGORY_ID IN (1, 2, 3)

不幸的是,MySQL 不支持那种允许您在单个数据库往返中完成所有这些的递归查询。

于 2013-02-18T12:34:25.627 回答
0

阅读用于对产品进行分组的嵌套集。 http://en.wikipedia.org/wiki/Nested_set_model

它允许您在关系数据库中创建一个很好的结构来将产品分配给类别。比大多数人提出的典型的 child->parent 模型要好得多。

于 2013-02-16T22:37:56.183 回答