Mysql SQL:分别与标签匹配的项目数

Mysql SQL:分别与标签匹配的项目数,mysql,sql,Mysql,Sql,我有以下四个表格: 我想实现的是产品过滤器,即: 列出所有标签类别 列出每个类别中的所有标签 选择标签后,它会过滤产品列表,以便在组内的标签之间存在“或”关系,在不同组的标签之间存在“和”关系。此查询已完成 选择一个或多个过滤器后,它将显示该过滤器的选择将添加到产品列表中的产品数量。除了查询每个标签的产品数量,我真的不知道如何实现这一点,但这会产生一个我更愿意避免的n+1问题 我想要的一个例子: 假设我有两个标签类别,颜色和大小。它们有多个标签,颜色有红色、绿色和蓝色;和小,中,大的大小

我有以下四个表格:

我想实现的是产品过滤器,即:

  • 列出所有标签类别
  • 列出每个类别中的所有标签
  • 选择标签后,它会过滤产品列表,以便在组内的标签之间存在“或”关系,在不同组的标签之间存在“和”关系。此查询已完成
  • 选择一个或多个过滤器后,它将显示该过滤器的选择将添加到产品列表中的产品数量。除了查询每个标签的产品数量,我真的不知道如何实现这一点,但这会产生一个我更愿意避免的n+1问题
我想要的一个例子:

假设我有两个标签类别,颜色和大小。它们有多个标签,颜色有红色、绿色和蓝色;和小,中,大的大小

  • 当用户选择红色和蓝色时,我想列出红色或蓝色的产品。(如我所说,此产品查询已完成)
  • 我还想列出所有的标签。对于颜色,我检查了红色和蓝色,但是对于绿色,我需要列出有多少绿色产品。对于尺寸,我需要列出中型、大型和小型;以及每种尺寸的红色或蓝色产品的数量如何编写此查询?
编辑: 我想要的基本上是Newegg左边的产品过滤器:

首先,您似乎需要按类别和标签进行分组

如果要使用同一查询列出所有产品并对其进行筛选,可以检查参数值,如果为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..”,应该可以了。谢谢你的贡献!