【问题标题】:counting products for each item in product filter计算产品过滤器中每个项目的产品
【发布时间】:2019-06-09 21:16:38
【问题描述】:

我需要帮助编写 SQL(或逻辑过程)来计算产品过滤器中每个项目的产品。

数据库结构:

products
--------
id|title


attributes
----------
id|title


attributes_values
---------------------
id|value|attribute_id


products_attributes
-------------------
product_id|attributes_value_id

我有带有属性的侧边栏过滤器,我需要获取每个属性的产品计数(过滤器中的行)。问题是计数应该已经受到已经选择的属性的限制。因此,当我选择了任何属性时,所有其他属性也必须计算具有所选属性的产品。

例如:我有两个属性,颜色(蓝色、白色)和材料(金属、木头)。当我选择蓝色时,我需要计算蓝色金属和蓝色木材的产品计数 - 计数的产品必须匹配所有选定的属性。

可以使用任何连接表或外部服务,但我不知道该怎么做,如何改变结构来做到这一点。

DBFiddle:https://www.db-fiddle.com/f/mMeUzm96xb9ZMHZonEktcD/1

感谢您的任何想法。

【问题讨论】:

  • 嗨,欢迎来到 stackoverflow。请提供minimal reproducible example,说明您是如何尝试自行解决此问题的。该社区旨在帮助人们学习,而不是提供免费的编码服务。
  • Eg: I have two properties, color (blue, white) and material (metal, wood). attributes_values 的数据库中的这些在哪里?一些示例数据甚至 DBFiddle 都会有所帮助。
  • 感觉你有很多attributes 表,例如你可以组合attributes_valuesproducts_attributes,但我仍然没有可以查找“颜色”或“的键”材料”。我会做类似id|product_id|key|value 之类的事情。此外,表格attributes 的用途尚不清楚。看一张桌子,因为我建议在products.id=products_attributes.product_id WHERE attr_key="color"attr_value="blue" 上加入products_attributes 很简单(请注意key 是保留字)
  • 没有预期结果的小提琴并不是非常有用
  • 我不知道如何查询得到这个结果,所以想要的结果只在fiddle的评论中。 db-fiddle.com/f/mMeUzm96xb9ZMHZonEktcD/2

标签: php mysql filtering


【解决方案1】:

第一步是将这些表attributesattributes_valuesproducts_attributes 组合成适当的形式,例如product_metaproduct_options 甚至product_attributes

每个产品与属性之间只有一对多的关系。例如,一个产品可以有很多属性,但一个属性只属于一个产品。请注意,这仍然允许您拥有重复的属性。例如,产品 1 没有理由不能有 2 个颜色属性。

为了确保您可以将其“规范化”到您拥有的级别,但这是不必要的,只会使 SQL 复杂化并在以后引起各种麻烦。所以,而不是什么? 2 多对多关系和一对多关系,您真正需要的只是一对多

所以我们从那里开始:

products
--------
id|title

product_attributes
id|product_id|attr_key|attr_value

现在为您查询

SELECT 
   COUNT(p.id)
FROM
   products p
JOIN
   product_attributes pa ON p.id = pa.product_id
WHERE
   (pa.attr_key="color" AND pa.attr_value="blue")

这将为您提供所有蓝色产品的数量(无论材料如何)。相当困难,但不完全是我们需要的。

添加材料有点困难,但可以通过再次加入属性来完成(并对值进行分组等),如下所示:

  SELECT 
     COUNT(p.id)
  FROM
     products p
  JOIN
     #instead of one table, with your schema you would need 3 (apx) joins here
     product_attributes pa ON p.id = pa.product_id
  JOIN
     #you would also need 3 joins here
     product_attributes pa1 ON p.id = pa1.product_id 
  WHERE
     pa.attr_key="color" AND pa.attr_value="blue"
     AND 
     pa1.attr_key="material"

基本上,我们正在选择所有具有“颜色”蓝色属性但也具有“材料”属性的产品{something}。

当您使用这样的键值存储并希望访问同一个表中的两个值时,这将需要在表上进行额外的连接。因此,如果您有一个非常复杂的架构,其中包含 3 个仅针对这些属性的表,您必须多次重现所有这些辅助连接。最好保持简单。

另请参阅这个 DB fiddle

https://www.db-fiddle.com/f/mdVypFwY7WsfHcgkasR7gE/1

CREATE TABLE products(
   id INT(10),
    title VARCHAR(250)
 );

 INSERT INTO products (id,title)VALUES(1,'foo');
 INSERT INTO products (id,title)VALUES(2,'bar');

 CREATE TABLE product_attributes(
   id INT(10),
   product_id INT(10),
   attr_key VARCHAR(250),
   attr_value VARCHAR(250)
 );

  INSERT INTO product_attributes (id,product_id,attr_key,attr_value)VALUES(1,1,'color', 'blue');
  INSERT INTO product_attributes (id,product_id,attr_key,attr_value)VALUES(2,1,'color', 'white');
  INSERT INTO product_attributes (id,product_id,attr_key,attr_value)VALUES(3,1,'material', 'metal');
  INSERT INTO product_attributes (id,product_id,attr_key,attr_value)VALUES(4,1,'material', 'wood');

  #say we also have plastic
  INSERT INTO product_attributes (id,product_id,attr_key,attr_value)VALUES(4,1,'material', 'plastic');

  INSERT INTO product_attributes (id,product_id,attr_key,attr_value)VALUES(1,2,'color', 'white');

上述查询的结果是13(注意我添加了第3 个材料),只有2 个你得到正确的计数。这是为了表明您可以拥有更多而不仅仅是 2。如果您想将其限制为仅 3 中的 2,请执行以下操作:

   WHERE
     pa.attr_key="color" AND pa.attr_value="blue"
     AND 
     pa1.attr_key="material" AND pa1.attr_value IN("wood", "metal")

您可以通过选择不带 attr 值来稍微验证这一点,这给出了 6,即 metal/bluemetal/whitewood/bluewood/white 和(在我的示例中)plastic/blue、@987654341 @。这是这些属性的所有可能组合。

最后一点是您可以在 attr_keyattr_value 上放置一个唯一索引作为复合键,这样可以防止重复的键/值对。

【讨论】:

  • 非常感谢,但我有两个问题。当我不仅有两个属性,而是 15 个属性(例如:宽度、高度、深度、重量、数量类、证书类等)时该怎么办,我必须为每个不同的 attr_key 做连接?第二,如何在一个查询中计算所有属性(包括产品数量)?有可能或者我必须迭代属性并获得每个属性的结果?
  • how to count all properties (with counts of products) 我不太清楚你的意思,你可以SELECT product_id, COUNT(id) as total FROM product_attributes GROUP BY product_id 这会给你每个产品ID和它拥有的属性数量。
  • 使用键值存储,您必须加入每个。每个产品都有的标准化属性应该是product 的一部分。因此,如果所有产品都有一个尺寸(不是相同尺寸,而是每个产品 1 个),则将其放入产品中。 Key\Value 的优点是在构建时不必知道密钥是什么,缺点是增加了复杂性。
  • 我的意思是逆计算,如何仍然计算属性的产品,所以结果将如下所示:每个 property_id 及其拥有的产品数量(仍然匹配所有已选择的属性)。你明白吗?
  • property_id 是什么意思? product_attributes.id ?每个人只能拥有一种产品。一对多。你必须给我一个你期望结果的例子(对于给定的模式)。例如,如果您想知道有多少产品具有“材料”属性,那么只需计算attr_key="material" 的位置即可,但有些产品可能有多个,所以您的意思是不同的产品(在这种情况下,产品 ID 上的组)
猜你喜欢
  • 2012-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-02
  • 1970-01-01
  • 1970-01-01
  • 2017-04-28
  • 1970-01-01
相关资源
最近更新 更多