mysql:选择菜单 - 取消选择结果中不存在的所有类别

时间:2012-01-09 03:27:26

标签: mysql nested-sets

使用mysql(和php)我试图隐藏选择菜单 类别不适用于项目选择。 基本上我被困住了,无法做到这一点。

Asos使用此技术浏览产品(http://www.asos.com/Men/Jeans/Cat/pgecategory.aspx?cid=4208)。

要明确的问题不是如何做ajax的东西,而是如何有效地使用mysql和php制作这样的系统。

我试图用嵌套集来解决这个问题:

    (1)items(22)----------------------------------
          |                           |
          |                           |
    (2)producs(7)                  (8)origin(21)
          |                           |
(3)single(4)-(5)bundle(6)             |
                             ---------------------
                             |                   |
                            (9)EU(14 )        (15)ASIA(20)   
                             |                   |   
                          ----------------      -----------------
                          |             |         |              |
                        (10)DU(11)  (12)PL(13)  (16)CN(17)   (18)JP(19)

菜单:
类型:
-single
-bundle

起源:
- 欧盟
-ASIA

国家:
-DU
-PL
-CN
-JP

让我们说数据库中有一个项目: 项目'1'位于:
-single
- 欧盟
-DU

项目类别表:

itemID - cat_lft - cat_rgt
  1        10        11
  1        7         12
  1        2         3

在菜单中选择DU应选择:
DU-EU-SINGLE

并取消选择其余的(返回一个数组?)因为现在只有一个项目。

您可以获取项目并比较结果是否存在于剩余类别中,但这听起来像使用了大量查询...

有什么建议从哪里开始?

1 个答案:

答案 0 :(得分:1)

这是我将如何做到的。确保您的产品仅使用树叶分类(即左=右+ 1)。因此,产品可以归类为“DU”,但不能归类为“原产地”或“ASIA”。

类别表:

  • CATEGORY_ID
  • 名称

产品表:

  • PRODUCT_ID
  • 名称
  • ...

类别_产品表:

  • CATEGORY_ID
  • PRODUCT_ID

确定已检查与未检查类别的SQL查询:

SELECT
    `categories`.`category_id`,
    `categories`.`name`,
    IFNULL(COUNT(`categories_products`.`id`), 0) AS `count` FROM `categories`

LEFT JOIN `categories` as `children` ON
    `children`.`left`  > `categories`.`left`  AND
    `children`.`right` < `categories`.`right`

JOIN `categories_products` ON
    `categories_products`.`category_id` = `children`.`category_id`

GROUP BY `categories`.`category_id`

如果“count”为0,则取消选中;否则,它会被检查,并且您知道该类别中有多少项目。这是未经测试的,因此可能需要进行一些调整。您肯定希望在category_id,product_id,left和right列上建立索引。

添加:用于选择一个或多个类别中的产品的SQL查询(请参阅下面的复合条件):

SELECT `products`.* FROM `categories`

JOIN `categories` as `children` ON
    `children`.`left`  >= `categories`.`left`  AND
    `children`.`right` <= `categories`.`right`

JOIN `categories_products` ON
    `categories_products`.`category_id` = `children`.`category_id`

JOIN `products` ON
    `products`.`product_id` = `categories_products`.`product_id`

WHERE `categories`.`category_id` IN (1,2,3,n,...)

GROUP BY `products`.`product_id`

添加:逻辑选择多个类别的产品,复合过滤(产品必须在所有类别中匹配):

您必须为所需的每个类别要求单独加入。请注意,这种类型的查询可能会变得很慢,因此您可以进行一些基准测试。使用多个查询(每个类别一个)可能会更好,将结果组合在应用程序代码中。

沿着同样的路线,我建议像产品表中的“单一与捆绑”之类的东西是ENUM,分类留给更抽象的结构(区域工作,传统的面向消费者, “逻辑”分类结构)不是简单的任何/或标志。