我需要帮助编写 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
感谢您的任何想法。
最佳答案
第一步是将这些表 attributes
、attributes_values
和 products_attributes
组合成适当的内容,例如 product_meta
或 product_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');
上述查询的结果是 1
和 3
(注意我添加了第三种 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/blue
、metal/white
和木头/蓝色
、木头/白色
和(在我的示例中)塑料/蓝色
、塑料/白色
。这是这些属性的所有可能组合。
最后一点是,您可以在 attr_key
和 attr_value
上放置唯一索引作为复合键,这将防止重复的键/值对。
关于php - 计算产品过滤器中每个项目的产品数量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54205998/