我有一个产品数据库,我想根据任意类别进行过滤。让我们说一个例子,我运行一个车库。我有一部分产品是汽车。
每辆车都应该有一系列属性,所有车辆都有相同数量和类型的属性;例如颜色:红色,门:2,制造:福特;将所有相同的属性设置为所有汽车的各种值。
Gut感觉告诉我最好在产品表中添加“color”,“doors”和“make”列。
但是:并非所有表中的产品都是汽车。也许我想在汽车页面上列出轮胎。显然,“颜色”和“门”不适用于轮胎。即便如此,如果用户选择color = red作为过滤器,我仍然希望显示轮胎,因为它们缺少颜色属性。
仔细研究它(我真的不是数据库人,所以如果这种方法很糟糕我道歉)我考虑过一个“属性”列,我可以用任意数量的任意命名属性填充,然后使用SQL字符串函数进行过滤。如果你仔细计划,我想你甚至可以在这里使用一点点。这对我来说似乎很骇人听闻,我有兴趣知道像亚马逊这样的大型网站是如何做到的。
这些方法有哪些问题,是否有人可以推荐任何替代方案或为我提供有关该主题的任何信息?
提前致谢
答案 0 :(得分:2)
您应该阅读有关数据库规范化的内容。在单个列中使用连接字符串作为值通常不是一个好主意。我做了一个非常小的sqlfiddle让你开始玩。这并没有真正解决你所有的问题,但它可能会引导你朝着正确的方向前进。
架构:
CREATE TABLE product (id int, name varchar(200), info varchar(200));
INSERT INTO product (id, name, info) VALUES (100, "Porsche", "cool");
...
INSERT INTO product (id, name, info) VALUES (103, "Tires", "you need them!");
CREATE TABLE attr (id int, product_id int, a_name varchar(200), a_value varchar(200));
INSERT INTO attr (id, product_id, a_name, a_value) VALUES (1, 100, "color", "black");
INSERT INTO attr (id, product_id, a_name, a_value) VALUES (2, 100, "doors", "2");
...
查询:
SELECT * FROM product INNER JOIN attr ON attr.product_id=product.id
WHERE attr.a_name="doors" AND attr.a_value = "2"
答案 1 :(得分:1)
将来读这篇文章的人,我设法得到了我想要的结果,感谢luksch花时间帮助我!感谢!!!
使用此布局:
CREATE TABLE product (id int, name varchar(200));
INSERT INTO product (id, name) VALUES (100, "Red Porsche");
INSERT INTO product (id, name) VALUES (101, "Red Ferrari V8");
INSERT INTO product (id, name) VALUES (102, "Red Ferrari V12");
INSERT INTO product (id, name) VALUES (103, "Blue Porsche");
INSERT INTO product (id, name) VALUES (104, "Blue Ferrari V8");
INSERT INTO product (id, name) VALUES (105, "Blue Ferrari V12");
INSERT INTO product (id, name) VALUES (106, "Snow Tires");
INSERT INTO product (id, name) VALUES (107, "Fluffy Dice");
CREATE TABLE attr (id int, product_id int, a_name varchar(200), a_value varchar(200));
INSERT INTO attr (id, product_id, a_name, a_value) VALUES (1, 100, "colour", "red");
INSERT INTO attr (id, product_id, a_name, a_value) VALUES (1, 101, "colour", "red");
INSERT INTO attr (id, product_id, a_name, a_value) VALUES (1, 101, "cylinders", "8");
INSERT INTO attr (id, product_id, a_name, a_value) VALUES (1, 102, "colour", "red");
INSERT INTO attr (id, product_id, a_name, a_value) VALUES (1, 102, "cylinders", "12");
INSERT INTO attr (id, product_id, a_name, a_value) VALUES (1, 103, "colour", "blue");
INSERT INTO attr (id, product_id, a_name, a_value) VALUES (1, 104, "colour", "blue");
INSERT INTO attr (id, product_id, a_name, a_value) VALUES (1, 104, "cylinders", "8");
INSERT INTO attr (id, product_id, a_name, a_value) VALUES (1, 105, "colour", "blue");
INSERT INTO attr (id, product_id, a_name, a_value) VALUES (1, 105, "cylinders", "12");
我达到了我想要的结果;这是两件事:
首先,我希望能够按属性选择产品,比如按颜色和圆柱体选择产品,还要显示任何既没有颜色也没有圆柱属性的产品,这是我通过此查询实现的:
SELECT DISTINCT product.id, name, a_value
FROM product
LEFT JOIN attr
ON product_id=product.id
WHERE
(
(a_name="colour" AND a_value="blue")
OR
(a_name IS NULL)
)
AND product.id IN
(
SELECT product.id
FROM product
LEFT JOIN attr
ON product_id=product.id
WHERE
(a_name="cylinders" AND a_value="12")
OR
(a_name IS NULL)
)
这列出了所有带有12个气缸的蓝色车,并且还列出了轮胎和蓬松的骰子,因为它们没有颜色或气缸数。这可以很容易地适用于过滤一个属性,或者您可以添加更多AND / IN子句来添加更多过滤器
我还希望能够列出所有相关属性(我在此示例中使用WHERE 1
,但实际上这将WHERE idfolders=?
列出与特定文件夹相关的所有属性)
SELECT DISTINCT a_value, a_name
FROM product
INNER JOIN attr
ON product_id=product.id
WHERE 1