Mysql SQL:分别与标签匹配的项目数
我有以下四个表格: 我想实现的是产品过滤器,即:Mysql SQL:分别与标签匹配的项目数,mysql,sql,Mysql,Sql,我有以下四个表格: 我想实现的是产品过滤器,即: 列出所有标签类别 列出每个类别中的所有标签 选择标签后,它会过滤产品列表,以便在组内的标签之间存在“或”关系,在不同组的标签之间存在“和”关系。此查询已完成 选择一个或多个过滤器后,它将显示该过滤器的选择将添加到产品列表中的产品数量。除了查询每个标签的产品数量,我真的不知道如何实现这一点,但这会产生一个我更愿意避免的n+1问题 我想要的一个例子: 假设我有两个标签类别,颜色和大小。它们有多个标签,颜色有红色、绿色和蓝色;和小,中,大的大小
- 列出所有标签类别
- 列出每个类别中的所有标签
- 选择标签后,它会过滤产品列表,以便在组内的标签之间存在“或”关系,在不同组的标签之间存在“和”关系。此查询已完成
- 选择一个或多个过滤器后,它将显示该过滤器的选择将添加到产品列表中的产品数量。除了查询每个标签的产品数量,我真的不知道如何实现这一点,但这会产生一个我更愿意避免的n+1问题
- 当用户选择红色和蓝色时,我想列出红色或蓝色的产品。(如我所说,此产品查询已完成)
- 我还想列出所有的标签。对于颜色,我检查了红色和蓝色,但是对于绿色,我需要列出有多少绿色产品。对于尺寸,我需要列出中型、大型和小型;以及每种尺寸的红色或蓝色产品的数量如何编写此查询?
首先,您似乎需要按类别和标签进行分组 如果要使用同一查询列出所有产品并对其进行筛选,可以检查参数值,如果为null,则可以显示所有产品
Select lc.title, l.title, count(Distinct p.Id) itemCount from Products p, Label_Product lp, Labels l, Label_categories lc
where
p.id = lp.product_id and l.id = lp.label_id and lc.id = l.label_category_id
and (l.ID = @label or @label is null)
and (lc.ID = @category or @category is null)
group by
lc.title, l.title, l.Id
动态构造(在应用程序中)以下查询
SELECT size, COUNT(*)
FROM tbl
WHERE color IN ('red', 'blue')
GROUP BY size;
这将告诉你有多少小的,中的,和大的东西,因为你只看阅读或蓝色的东西
每次用户更改选项时,您都会重新生成并重新运行查询。假设用户选择了一些类型和销售商,但没有选择制造商。然后,WHERE
子句如下所示
WHERE type IN (...)
AND manufacturer IN (...)
也就是说,您需要准备好根据用户迄今为止选择的内容构建一个和列表
这是申请代码;在SQL中完成所有工作是不现实的。尝试以下方法:
--for colors category
select l.title as label_title
, count(product_id) as number_of
from label_product lp
inner join labels l on lp.label_id = l.id
--where label_category_id = 'id_of_colors_category' --if you can use label_category_id directly, or if you must use title of category:
where l.label_category_id in(select id from label_categories where title = 'colors')
and exists(
select 1 from products p
where p.id = pl.product_id
--global rules for products, for example:
----and p.deleted = 0
----and p.category = 'cars'
--rules for user selected conditions
----for example rule for sizes
and exists(
select 1 from label_product clp
--where label_id in (....) --if you can use label_id's directly
where clp.product_id = p.id
and label_id in(
select id from labels
where label_category_id = 'id_of_sizes_category'
and title in('medium', 'large', 'small')
)
)
----example 2nd rule for types
and exists(
select 1 from label_product clp
where clp.product_id = p.id
and label_id in(
select id from labels
where label_category_id = 'id_of_types_category'
and title in('type1', 'type2', 'type3')
)
)
--don't add rule for current label_category - for this example colors
--end of user selected conditions
)
group by l.title
这是用MySQL标记的,所以这里有一个MySQL方法。
假设1和2是红色和蓝色的ID,并且尚未选择大小过滤器。然后,第一个查询为您提供每个颜色标签,其中有多少产品与大小过滤器匹配。同样,最后一个查询将为您提供每个尺寸标签,其中有多少产品与颜色过滤器匹配
SET @selected_color_labels = '1,2';
SET @selected_size_labels = NULL;
SELECT l.id, count(DISTINCT lp.product_id)
FROM label_categories lc
INNER JOIN labels l ON l.label_category_id = lc.id
INNER JOIN label_product lp ON lp.label_id = l.id
INNER JOIN label_categories lc2 ON lc2.title = 'size'
INNER JOIN labels l2 ON l2.label_category_id = lc2.id AND ifNull(find_in_set(l2.id, @selected_size_labels) > 0, TRUE)
INNER JOIN label_product lp2 ON lp2.label_id = l2.id AND lp2.product_id = lp.product_id
WHERE lc.title = 'color'
GROUP BY l.id;
SELECT l.id, count(DISTINCT lp.product_id)
FROM label_categories lc
INNER JOIN labels l ON l.label_category_id = lc.id
INNER JOIN label_product lp ON lp.label_id = l.id
INNER JOIN label_categories lc2 ON lc2.title = 'color'
INNER JOIN labels l2 ON l2.label_category_id = lc2.id AND ifNull(find_in_set(l2.id, @selected_color_labels) > 0, TRUE)
INNER JOIN label_product lp2 ON lp2.label_id = l2.id AND lp2.product_id = lp.product_id
WHERE lc.title = 'size'
GROUP BY l.id;
请以表格形式提供样本数据和预期结果。如前所述,问题似乎含糊不清。一些示例数据将有助于理解您的需求。我想要的正是以下内容:-基本上是左侧的产品过滤器。在电子商务中,这称为分面搜索。这些产品在数据库后端方面要求很高。有完整的数据处理层来处理这种功能。不要认为您会在stackoverflow中找到一个(全面的)真实应用程序的答案。完全商业化、昂贵的产品就是为了解决这个问题而开发的。@nXu这个问题是几个月前提出的,现在你有了一些答案,也许是时候决定哪一个是最好的答案了,或者如果没有一个是最好的答案,那么就对它们进行一些评论,解释为什么这些不是你想要的答案。也许你想要COUNT(*)
而不是SUM(p.Id)
?COUNT(x)
检查x
是否为NULL
<代码>计数(*)
在不需要该测试时使用。请记住,连接
是在计数
之前完成的。你可能会得到一个膨胀值!我已经把它改为“count(Distinct..”,应该可以了。谢谢你的贡献!