Php 检索邻接列表模型中某些类别下的所有产品的SQL查询

Php 检索邻接列表模型中某些类别下的所有产品的SQL查询,php,mysql,sql,many-to-many,Php,Mysql,Sql,Many To Many,我有一个带有邻接列表方法的数据库,用于处理产品分类,其中一个产品可以在多个类别下找到。查看以下数据库布局: cats id parent title desc 1 0 top top level 2 1 Electronics 3 2 Gaming 4 2 Computers 5 4 Tablets 6 1

我有一个带有邻接列表方法的数据库,用于处理产品分类,其中一个产品可以在多个类别下找到。查看以下数据库布局:

cats
id    parent    title           desc
1     0         top             top level
2     1         Electronics
3     2         Gaming
4     2         Computers
5     4         Tablets
6     1         Food
7     3         Xbox

products
id        title         qty
1         ToshibaTV     5
2         I-PAD2        9
3         Laser Pen     24
4         Asus Notebook 5


cats_products
id   product_id   cat_id 
1    2            3
2    2            5
3    1            2
4    3            2
5    4            4 
在上面的示例中,我需要一个SQL查询,它能够检索Electronics类别中的所有产品以及任何级别的子类别(例如Xbox,它不是Electronics的直接子类别),而无需重复在多个类别(如I-PAD2)中找到的产品


我可以借助PHP中的应用程序来实现这一点,但我想知道是否可以在MySQL中使用纯sql来实现这一点?

这是您问题的第一部分。你能更详细地解释一下儿童部分吗。我想这和猫的父母有关

试试这个:

SELECT distinct(p.title) 
FROM cats AS c
JOIN cats_products AS cp
ON cp.cat_id = c.id AND c.title = "Electronics"
JOIN products AS p
ON p.id = cp.product_id;
样本数据:

CREATE TABLE cats
    (`id` int, `parent` int, `title` varchar(11), `desc` varchar(9))
;

INSERT INTO cats
    (`id`, `parent`, `title`, `desc`)
VALUES
    (1, 0, 'top', 'top level'),
    (2, 1, 'Electronics', ''),
    (3, 2, 'Gaming', ''),
    (4, 2, 'Computers', ''),
    (5, 4, 'Tablets', ''),
    (6, 1, 'Food', ''),
    (7, 3, 'Xbox', '')
;



CREATE TABLE products
    (`id` int, `title` varchar(13), `qty` int)
;

INSERT INTO products
    (`id`, `title`, `qty`)
VALUES
    (1, 'ToshibaTV', 5),
    (2, 'I-PAD2', 9),
    (3, 'Laser Pen', 24),
    (4, 'Asus Notebook', 5)
;



CREATE TABLE cats_products
    (`id` int, `product_id` int, `cat_id` int)
;

INSERT INTO cats_products
    (`id`, `product_id`, `cat_id`)
VALUES
    (1, 2, 3),
    (2, 2, 5),
    (3, 1, 2),
    (4, 3, 2),
    (5, 4, 4)
;

编辑第二部分

SELECT distinct(v.title) FROM products AS v
JOIN (
  SELECT Y.product_id FROM cats_products AS Y
    JOIN(
      SELECT distinct(z.id) FROM cats AS Z
        JOIN
          (SELECT c.parent
           FROM cats AS c
           JOIN cats_products AS cp
           ON cp.cat_id = c.id 
           AND c.title = "Electronics") AS X
         ON x.parent = z.parent) AS W
    ON W.id = Y.cat_id) AS u
ON u.product_id = v.id
;
样本数据

CREATE TABLE cats
    (`id` int, `parent` int, `title` varchar(11), `desc` varchar(9))
;

INSERT INTO cats
    (`id`, `parent`, `title`, `desc`)
VALUES
    (1, 0, 'top', 'top level'),
    (2, 1, 'Electronics', ''),
    (3, 2, 'Gaming', ''),
    (4, 2, 'Computers', ''),
    (5, 4, 'Tablets', ''),
    (6, 1, 'Food', ''),
    (7, 3, 'Xbox', '')
;



CREATE TABLE products
    (`id` int, `title` varchar(13), `qty` int)
;

INSERT INTO products
    (`id`, `title`, `qty`)
VALUES
    (1, 'ToshibaTV', 5),
    (2, 'I-PAD2', 9),
    (3, 'Laser Pen', 24),
    (4, 'Asus Notebook', 5),
    (5, 'French Fries', 50)
;



CREATE TABLE cats_products
    (`id` int, `product_id` int, `cat_id` int)
;

INSERT INTO cats_products
    (`id`, `product_id`, `cat_id`)
VALUES
    (1, 2, 3),
    (2, 2, 5),
    (3, 1, 2),
    (4, 3, 2),
    (5, 4, 4),
    (5, 5, 6)

;
这是我对您问题的解释:每个类别都有一个父类别,您希望选择具有相同父类别的所有其他类别。具有相同父类别的所有产品更具体。

使用邻接列表模型很难做到这一点。正如@Mike所建议的,使用嵌套的集合模型将使这变得更加容易。或者,通过php代码实现这一点会更容易

但是,假设您知道可能有多少个父子级别(或者您可以假设不超过X),您可以尝试这样的方法。如果MySQL支持CTE,这将更容易阅读,但不幸的是,它不支持CTE。在这个例子中,我已经深入了4个层次——你可以得到深入的想法

SELECT p.Id, p.Title, p.Qty
FROM Products p
   JOIN Cats_Products cp on p.id = cp.product_id
WHERE cp.cat_id IN (
   SELECT c.id
   FROM Cats c
   WHERE c.title = 'Electronics'
   UNION ALL
   SELECT c2.id
   FROM Cats c
      LEFT JOIN Cats c2 ON c.id = c2.parent
   WHERE c.title = 'Electronics'
   UNION ALL
   SELECT c3.id
   FROM Cats c
      LEFT JOIN Cats c2 ON c.id = c2.parent
      LEFT JOIN Cats c3 ON c2.id = c3.parent
   WHERE c.title = 'Electronics'
   UNION ALL
   SELECT c4.id
   FROM Cats c
      LEFT JOIN Cats c2 ON c.id = c2.parent
      LEFT JOIN Cats c3 ON c2.id = c3.parent
      LEFT JOIN Cats c4 ON c3.id = c4.parent
   WHERE c.title = 'Electronics'
)
GROUP BY p.Id, p.Title, p.Qty
这是我的答案


祝您好运。

您可能希望查看用于存储类别层次结构的嵌套集模型,然后只需找到该项目所属的所有类别,并找到每个@Mike的子类别,这是一个非常重要的注释,我认为你应该将其表述为一个答案,这样你就可以因为提供了合理的资源来处理这个问题而得到适当的奖励:)@Mike这是一个很好的教程,但它将类别产品关系处理为一对多而不是多对多@sєєєєm sєєєm你能根据你提供的数据样本向我们展示一下预期的结果吗?我认为这不是OP想要做的——它只搜索顶层,而OP想要搜索顶层和所有子层(使用邻接列表模型很难做到这一点)祝你好运。@sgedes如果那样的话,他可以无视我的回答,接受你的。太好了。在应用程序的帮助下,子类别的限制不是一个重要的问题,在应用程序中,您的完美查询可能会循环以写入更多级别。然而,你和@Mike认为嵌套集模型更容易满足这个需求,所以,你能告诉我如何将它添加到答案中吗?事实上,我使用CakePHP,如果我决定使用它,CakePHP的树行为支持嵌套模型,了解嵌套集模型是如何做到这一点的会很有用吗?非常感谢。我喜欢这个网站,非常接近我为同一个问题所使用的sql。很高兴看到我离基地不远了。回答得好