从子类别sql查询中获取项目

时间:2013-02-15 14:27:24

标签: mysql database database-design

我有以下数据库结构:

[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
.   .   ...

PRODUCT 的示例数据:

1   Sony
2   Sharp
3   Samsung
.   ...

PRODUCT_TO_CATEGORY 的示例数据:

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

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

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

2 个答案:

答案 0 :(得分:1)

  

父级(默认为0)

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


  

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

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

出于性能原因,这种冗余有时可能是合理的,但是您必须使用数据一致性来平衡它们。在这种情况下,没有良好的声明方式来保持冗余数据与“主”数据同步 - 您必须通过触发器或(上帝禁止)应用程序代码来执行此操作,并且您可能会在此过程中引入并发错误,除非你仔细考虑你的锁定策略非常非常


  

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

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

enter image description here

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

您的数据如下:

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)

  5. 不幸的是,MySQL不支持那种允许你在单个数据库往返中完成所有操作的递归查询。

答案 1 :(得分:0)

了解用于分组产品的嵌套集。 http://en.wikipedia.org/wiki/Nested_set_model

它允许您在关系数据库中创建一个漂亮的结构,以将产品分配给类别。比大多数人提出的典型的孩子 - >父母模型要好得多。