我需要帮助编写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
感谢任何想法。
答案 0 :(得分:0)
那么第一步就是将这些表attributes
,attributes_values
和products_attributes
组合成诸如product_meta
或product_options
甚至是{{1} }。
每个产品与属性之间只有一对多的关系。例如,一个产品可以具有许多属性,但是一个属性仅属于一个产品。请注意,这仍然允许您具有重复的属性。例如,没有理由产品1不能具有2种颜色属性。
为确保可以将其“规范化”到您拥有的级别,但这是不必要的,并且只会使SQL复杂化,并在以后引起各种麻烦。那么而不是什么呢? 2多对多关系和一对多关系,您真正需要的就是一对多
所以我们将从这里开始:
product_attributes
现在开始查询
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")
基本上,我们正在选择所有具有“颜色”蓝色属性和“材料” {something}属性的产品。
当您使用这样的键值存储并想要访问同一张表中的两个值时,这将需要在表上进行额外的联接。因此,如果您有一个非常复杂的架构,仅具有3个表用于这些属性,则必须多次重现所有这些辅助联接。最好保持简单。
也请参阅此数据库小提琴
https://www.db-fiddle.com/f/mdVypFwY7WsfHcgkasR7gE/1
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"
上述查询的结果是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个材料),只有2个您得到了正确的计数。这表明您只能拥有2个。如果您想将其限制为3个中的2个,请执行以下操作:
3
您可以选择不带attr值来对此进行一点验证,这将得到 WHERE
pa.attr_key="color" AND pa.attr_value="blue"
AND
pa1.attr_key="material" AND pa1.attr_value IN("wood", "metal")
,分别为6
,metal/blue
和metal/white
,wood/blue
和(在我的示例中)wood/white
,plastic/blue
。这些属性的所有可能组合都是这样。
最后一点是您可以在plastic/white
和attr_key
上放置一个唯一索引作为复合键,这样可以防止重复的键/值对。