我有一个有多对多关系的实体:
有Product
,可以有许多类别和许多标签。 Tag
或Category
也可以有很多产品。
现在的架构是:
products
-------------
product_id
name
categories
-------------
category_id
name
tags
-------------
tag_id
name
products_categories
-------------
product_id
category_id
products_tags
-------------
product_id
tag_id
我需要在一个页面中显示包含所有标签和类别的产品列表
问题是我执行的查询数量是2n + 1
,其中n是页面中列出的产品数量。
基本上我先做的是:
select product_id, name from products
然后在我的应用程序的循环中,我执行这些查询(伪代码):
tags = []
categories = []
for each product
tags[product_id] = select t.tag_id, t.name
from products_tags as pt
join tags t
on pt.tag_id = t.tag_id
where pt.product_id = {product_id}
categories[product_id] = select c.category_id, c.name
from products_categories as pc
join categories c
on pc.category = c.category_id
where pc.product_id = {product_id}
end for each
是否有一种很好的方法可以使执行的查询数量与查询的记录数无关?
的修改
对于每种产品,我需要以这种格式显示数据:
-------------------------------------------------------
| Product name: A good smartphone |
| Categories: Tech, Smartphone |
| Tags: smartphone, some-smartphone-brand, 4g |
| |
-------------------------------------------------------
答案 0 :(得分:0)
你可以试试这个(它依次使用带有标签和类别的连接,并用列table_type来区分它们):
select *, 'CAT' as table_type
from products p left join products_categories pc left join categories c
ON p.product_id = pc.product_id and pc.category_id = c.category_id
UNION ALL
select *, 'TAG' as table_type
from products p left join products_tags pt left join tags t
ON p.product_id = pt.product_id and pt.tag_id = t.tag_id
order by p.product_id
答案 1 :(得分:0)
您可以使用单个查询从数据库和应用程序级别获取所有信息,根据您的需要构建数据。下面的查询将多次返回每个产品,但标签/类别不同。
select p.product_id, p.name, t.tag_id, t.name tag_name, c.category_id, c.cat_name
from product p
join products_tags as pt on pt.product_id = p.product_id
join tags t on pt.tag_id = t.tag_id
join products_categories as pc on pc.product_id = p.product_id
join categories c on pc.category = c.category_id
order by p.product_id
伪代码
products = []
tags = []
categories = []
var productObj= {};
var product_id =false;
for each product
/**
* If product_id != product.id from loop iteration it means this is different product from previous iteration, Push this product object in `products[]`
*/
if(product.id != product_id){
products[product.id] = product;
product_id = product.id;
}
/** you can put additional check here before insert in array if value is not present `products[product.id][tags]` */
products[product.id][tags][] = tag_name;
/** you can put additional check here before insert in array if value is not present `products[product.id][categories]` */
products[product.id][categories][]= cat_name;
end for each
产品的样本对象/数据结构
[
1 => [
name => A good smartphone,
categories => [Tech, Smartphone],
tags => [smartphone, some-smartphone-brand, 4g]
],
2 => [
name: Another product,
categories => [Cat1, Cat2],
tags => [Tag1, Tag2, .....]
],
.....
]