php - 计算产品过滤器中每个项目的产品数量

标签 php mysql filtering

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

数据库结构:

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


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


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


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

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

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

可以使用任何连接表或外部服务,但我不知道如何做到这一点,也不知道如何更改结构来实现它。

DBFiddle:https://www.db-fiddle.com/f/mMeUzm96xb9ZMHZonEktcD/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")

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

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

  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"

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

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

另请参阅此数据库 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(注意我添加了第三种 Material ),只要 2 就可以得到正确的计数。这是为了表明您可以拥有更多,而不仅仅是 2 个。如果您想将其限制为 3 个中的两个,请执行以下操作:

   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/white木头/蓝色木头/白色和(在我的示例中)塑料/蓝色塑料/白色。这是这些属性的所有可能组合。

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

关于php - 计算产品过滤器中每个项目的产品数量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54205998/

相关文章:

PHP 单行代码检查数组中是否有任何值超过 5

php - 如何使用PHP脚本处理ajax表单参数

php - MySQL/PHP : Use inner join if value isn't 0

MySQL:创建一个带有外键的表,该外键引用由外键组成的主键

c# - linq 按类类型过滤

php - 更改azure php webrole上的文档根目录

php - MySQL(i) "Too many connections"怎么办?

javascript - 使用下拉列表 jquery 插件过滤页面上的 div

php - 从数组中提取负值和非负值

php - 访问 PHP 中的特定列