我目前陷入困境。情景是这样的。我的产品可能与多个类别相关联。数据结构如下所示:
Products Table:
product_id name
1 Lemon
2 Kiwis
3 Cheese
产品到类别表
product_id category_id
1 1
1 2
1 3
2 1
2 3
3 2
3 4
类别表(在查询中不需要,但在此处添加它以帮助可视化正在发生的事情)
category_id name
1 Fruit
2 Yellow
3 Round
4 Dairy
我在这里苦苦挣扎的是,最初我想要获得所有水果类产品(类别ID 1),但我也想检查水果是否是黄色。请记住,黄色不会是唯一的过滤器,有时我会想要返回黄色和橙色的水果,但是因为奶酪是黄色的,所以它不能归还,因为它不是水果。然而,为了让事情变得更容易,我总是知道我将把水果类作为基础。
数据库结构不能像opencart数据库结构那样改变。
以下是我的尝试:
SELECT GROUP_CONCAT(DISTINCT p2c2.category_id SEPARATOR ',') as categories
FROM oc_product_to_category p2c
LEFT JOIN oc_product p ON (p.product_id = p2c.product_id)
LEFT JOIN oc_product_to_category p2c2 ON (p.product_id = p2c2.product_id)
WHERE p2c.category_id IN ('1','2')
这种作品除了会返回奶酪之外。
注意:我使用Group Concat,因为在所有这一切的最后,我的目标是返回与这些类别相匹配的产品,但根据过滤器,我想从匹配此产品的产品中返回另一个类别列表标准。所以:
情景:
获取符合类别标准的产品 返回这些产品的类别。
非常感谢任何帮助。
答案 0 :(得分:6)
此类问题称为关系划分。
有两种常见的解决方案:
第一个解决方案将匹配类别组合在一起,并与固定字符串进行比较:
SELECT p2c.product_id
FROM oc_product_to_category p2c
GROUP BY p2c.product_id
HAVING GROUP_CONCAT(p2c.category_id SEPARATOR ',' ORDER BY p2c.category_id) = '1,2'
第二个解决方案为每个必需值执行JOIN
:
SELECT p.product_id
FROM oc_product p
INNER JOIN oc_product_to_category p2c1
ON (p.product_id = p2c1.product_id AND p2c1.category_id = 1)
INNER JOIN oc_product_to_category p2c2
ON (p.product_id = p2c2.product_id AND p2c2.category_id = 2)
我在演示文稿SQL Query Patterns, Optimized中介绍了这些解决方案。我在测试中发现,连接解决方案的性能要好得多。
@ Tom的建议是对的,这是完整查询中的样子:
SELECT p.product_id, GROUP_CONCAT(p2c3.category_id SEPARATOR ',') AS categories
FROM oc_product p
INNER JOIN oc_product_to_category p2c1
ON (p.product_id = p2c1.product_id AND p2c1.category_id = 1)
INNER JOIN oc_product_to_category p2c2
ON (p.product_id = p2c2.product_id AND p2c2.category_id = 2)
INNER JOIN oc_product_to_category p2c3
ON (p.product_id = p2c3.product_id)
GROUP BY p.product_id;
@Tom建议的DISTINCT
不一定是必要的,因为你的p2c表应该对(product_id,category_id)有一个UNIQUE约束。