简体   繁体   English

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

[英]SQL query to retrieve all products under some categories in Adjacency List Model

I have a database with an Adjacency List approach to handle categorization of products in which one product may be found under many categories. 我有一个带有邻接列表方法的数据库来处理产品的分类,其中一个产品可以在许多类别下找到。 Get a look at the following database layout: 看看以下数据库布局:

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 

In the above example I need an SQL query that is able to retrieve all the products found in Electronics category and any child category of it with any level (Xbox for example which it is not directly child of Electronics) without repeat of the product that found in more than one category like I-PAD2. 在上面的例子中,我需要一个SQL查询,它能够检索电子类别中的所有产品及其任何级别的任何子类别(例如Xbox不是电子产品的直接子项),而不重复发现的产品在不止一个类别,如I-PAD2。

I could able to do this with the help of the application in PHP but I wonder if it is possible to do it using just pure sql in MySQL? 我可以在PHP的应用程序的帮助下做到这一点,但我想知道是否可以在MySQL中使用纯sql做到这一点?

What you're trying to do is rather difficult using the Adjacency List Model. 使用邻接列表模型,您要做的事情相当困难。 As @Mike suggested, using a Nested Set Model would make this so much easier. 正如@Mike建议的那样,使用嵌套集模型会使这更容易。 Or alternatively doing it via your php code would even be easier. 或者通过您的PHP代码执行它甚至会更容易。

However, assuming you know how many parent-child levels there could be (or you can assume there wouldn't be more than X), you can try something like this. 但是,假设您知道可能有多少父子级别(或者您可以假设不会超过X),您可以尝试这样的事情。 This would be easier to read if MySQL supported CTEs, but unfortunately, it does not. 如果MySQL支持CTE,这将更容易阅读,但不幸的是,它没有。 In this example, I've gone 4 levels deep -- you can get the idea of going deeper. 在这个例子中,我已经深入了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

And here is the SQL Fiddle . 这是SQL小提琴

Good luck. 祝好运。

This the first part of you question. 这是你提问的第一部分。 Could you explain the child part in more detail. 你能否更详细地解释孩子的部分? I guess it has something to do with parent in cats. 我想这与猫的父母有关。

Try this: 试试这个:

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;

SAMPLE DATA: 样本数据:

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)
;

SQL FIDDLE DEMO SQL FIDDLE DEMO

EDIT Second part : 编辑第二部分

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
;

Sample data 样本数据

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)

;

This is my interpretation of your question: Every category has a parent and you want to select all other categories with the same parent. 这是我对您的问题的解释:每个类别都有一个父级,您希望选择具有相同父级的所有其他类别。 More specific all products for with the same parent category. 更具体的所有产品具有相同的父类别。 SQL FIDDLE DEMO SQL FIDDLE DEMO

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM