2009-03-04 162 views
1

我不确定这是否可能在MySQL中。这里是我的表: -mySQL查询选择儿童

分类表:

  • ID
  • PARENT_ID(指向Categories.id)

我使用上表中的所有地图类别和子类别。

产品表:

  • ID
  • CATEGORY_ID

产品表指向它所属的子类别编号CATEGORY_ID。

例如如果我有玩具>教育>美国广播公司ABC是产品,玩具是类别和教育是子类别,那么ABC将有category_id为2.

现在的问题是,我想使用SQL查询来显示所有产品(在所有子类别及其子类别中,n级别)。

例如为:

select * from categories,products where category.name = 'Toys' and .... 

上述查询应显示从教育其产品和所有其他子类别及其子类别。

这可能使用mySQL查询吗?如果不是我有什么选择?我想避免PHP递归。

更新:基本上我想通过在产品表中添加匹配列来显示主要类别中的前10位产品。

回答

5

我在之前需要做同样事情的项目中所做的工作,我添加了两个新列。

  • i_depth:类别有多深
  • nvc_breadcrumb int值:在面包屑型格式

然后类别的完整路径我添加了一个触发器,里面的表分类信息做到以下几点(全部三次更新都在同一个触发器)...

-- Reset all branches 
UPDATE t_org_branches 
    SET nvc_breadcrumb = NULL, 
    i_depth = NULL 

-- Update the root branches first 
UPDATE t_org_branches 
    SET nvc_breadcrumb = '/', 
     i_depth = 0 
    WHERE guid_branch_parent_id IS NULL 

-- Update the child branches on a loop 
WHILE EXISTS (SELECT * FROM t_branches WHERE i_depth IS NULL) 
    UPDATE tobA 
     SET tobA.i_depth = tobB.i_depth + 1, 
      tobA.nvc_breadcrumb = tobB.nvc_breadcrumb + Ltrim(tobA.guid_branch_parent_id) + '/' 
     FROM t_org_branches AS tobA 
      INNER JOIN t_org_branches AS tobB ON (tobA.guid_branch_parent_id = tobB.guid_branch_id) 
     WHERE tobB.i_depth >= 0 
      AND tobB.nvc_breadcrumb IS NOT NULL 
      AND tobA.i_depth IS NULL 

然后只需要对你的产品表的连接的类别ID和做一个“LIKE'%/ [CATEGORYID] /%'”。请记住,这是在MS SQL中完成的,但它应该很容易转换为MySQL版本。

它可能只是足够兼容剪切和粘贴(在表和列名称更改后)。


的解释扩展...

t_categories(因为它现在站立)...

Cat Parent CategoryName 
1 NULL MyStore 
2 1  Electronics 
3 1  Clothing 
4 1  Books 
5 2  Televisions 
6 2  Stereos 
7 5  Plasma 
8 5  LCD 

t_categories(修改后)...

Cat Parent CategoryName Depth Breadcrumb 
1 NULL MyStore   NULL NULL  
2 1  Electronics  NULL NULL 
3 1  Clothing  NULL NULL 
4 1  Books   NULL NULL 
5 2  Televisions  NULL NULL 
6 2  Stereos   NULL NULL 
7 5  Plasma   NULL NULL 
8 5  LCD    NULL NULL 

t_categories (使用我给出的脚本后)

Cat Parent CategoryName Depth Breadcrumb 
1 NULL MyStore   0  / 
2 1  Electronics  1  /1/ 
3 1  Clothing  1  /1/ 
4 1  Books   1  /1/ 
5 2  Televisions  2  /1/2/ 
6 2  Stereos   2  /1/2/ 
7 5  LCD    3  /1/2/5/ 
8 7  Samsung   4  /1/2/5/7/ 

t_products(因为你拥有了它,现在,没有修改)...

ID Cat Name 
1 8 Samsung LNT5271F 
2 7 LCD TV mount, up to 36" 
3 7 LCD TV mount, up to 52" 
4 5 HDMI Cable, 6ft 

加入类别和产品(其中类别是C,产品是P)

C.Cat Parent CategoryName Depth Breadcrumb ID p.Cat Name 
1 NULL MyStore   0  /   NULL NULL NULL 
2 1  Electronics  1  /1/   NULL NULL NULL 
3 1  Clothing  1  /1/   NULL NULL NULL 
4 1  Books   1  /1/   NULL NULL NULL 
5 2  Televisions  2  /1/2/  4 5  HDMI Cable, 6ft 
6 2  Stereos   2  /1/2/  NULL NULL NULL 
7 5  LCD    3  /1/2/5/  2 7  LCD TV mount, up to 36" 
7 5  LCD    3  /1/2/5/  3 7  LCD TV mount, up to 52" 
8 7  Samsung   4  /1/2/5/7/ 1 8  Samsung LNT5271F 

现在假设产品表更加完整,因此每个类别中都有东西,并且没有NULL,您可以执行“Breadcrumb LIKE'%/ 5 /%'”来获取我提供的最后一个表格的最后三个项目。请注意,它包含该类别的直接项目和子项目(如Samsung电视)。如果你只想要特定的分类项目,只需做一个“c.cat = 5”。

+0

看起来不错。我会试试这个。 – 2009-03-05 04:50:24

0

表格分类有多大?您可能需要将其缓存在应用程序级别并构建适当的查询:...其中id在(2,3,6,7)

另外,最好是通过id获取类别,这是它们的唯一ID ,索引和快速,而不是按名称查找。

+0

我如何在应用层面实现这一目标?递归是唯一正确的方法? – 2009-03-04 05:29:34

+0

如果表格只有100行很大,那么您可以简单地在类别中选择*并在应用程序级别上操作(汇编)结构。 – cherouvim 2009-03-04 06:41:51

1

将一列添加到Categories表中,该表中将包含每个组的完整逗号分隔树。使用你的例子,子类别教育会把它当作树'1,2',其中1 =玩具,2 =教育(包括它本身)。下一个嵌套级别的类别将继续添加到树中。

要获得所有产品在一组,你使用MySQL的FIND_IN_SET功能,像这样

SELECT p.ID 
FROM Products p INNER JOIN Categories c ON p.category_ID = c.ID 
WHERE FIND_IN_SET(your_category_id, c.tree) 

我不会使用大表这种方法,因为我不认为这个查询就可以使用索引。

0

袒护我,因为我从来没有做过这样的事情。

BEGIN 
    SET cat = "5"; 
    SET temp = ""; 

    WHILE STRCMP(temp, cat) != 0 DO 
    SET temp = cat; 
    SET cat = SELECT CONCAT_WS(GROUP_CONCAT(id), cat) FROM Categories GROUP BY (parent_id) HAVING FIND_IN_SET(parent_id, cat); 
    END LOOP; 
END; 

SELECT * FROM products WHERE FIND_IN_SET(category_id, cat) 

我几乎可以保证上述不会工作,但你可以看到我正在尝试做什么。我得到了这一点,我只是决定不完成查询的结束(选择每个类别的前N),对不起。 :P

1

一种方法是维护一个包含祖先到后代关系的表。您可以查询此特定表并获取所有家属的列表。

5

我认为最简单的方法是使用嵌套集模型。实施起来有点复杂,但功能强大。 MySQL有一个名为Managing Hierarchical Data in MySQL的教程。其中一位大型SQL大师Joe Celko写了同样的东西here。如果你需要更多的信息,请看Troel's links on storing hierarchical data

在我的情况下,我会远离使用RDBMS来存储这种数据并使用图形数据库,因为在这种情况下的数据实际上是有向图。

1

假设MySQL,在PHP中很难避免递归。

你的问题本质上是如何模仿Oracle在MySQL中的语法CONNECT BY PRIOR。人们问这个questionrepeatedly但它是一个从未进入MySQL的功能,并且通过存储过程实现可能不会工作,因为(现在)stored functions cannot be recursive

当心迄今为止提供的数据库克鲁日。

最好的信息,到目前为止都是three links from nawroth