SQL按属性过滤(设计)

时间:2013-05-03 08:48:58

标签: sql database filter

我有一个产品数据库,我想根据任意类别进行过滤。让我们说一个例子,我运行一个车库。我有一部分产品是汽车。

每辆车都应该有一系列属性,所有车辆都有相同数量和类型的属性;例如颜色:红色,门:2,制造:福特;将所有相同的属性设置为所有汽车的各种值。

Gut感觉告诉我最好在产品表中添加“color”,“doors”和“make”列。

但是:并非所有表中的产品都是汽车。也许我想在汽车页面上列出轮胎。显然,“颜色”和“门”不适用于轮胎。即便如此,如果用户选择color = red作为过滤器,我仍然希望显示轮胎,因为它们缺少颜色属性。

仔细研究它(我真的不是数据库人,所以如果这种方法很糟糕我道歉)我考虑过一个“属性”列,我可以用任意数量的任意命名属性填充,然后使用SQL字符串函数进行过滤。如果你仔细计划,我想你甚至可以在这里使用一点点。这对我来说似乎很骇人听闻,我有兴趣知道像亚马逊这样的大型网站是如何做到的。

这些方法有哪些问题,是否有人可以推荐任何替代方案或为我提供有关该主题的任何信息?

提前致谢

2 个答案:

答案 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