【问题标题】:SQL Filter by attributes (Design)SQL 按属性过滤(设计)
【发布时间】:2013-04-27 14:52:22
【问题描述】:

我有一个想要按任意类别过滤的产品数据库。举个例子,我经营一个车库。我有一部分产品是汽车。

每辆汽车都应该有一个属性集合,所有汽车都有相同数量和类型的属性;例如颜色:红色,门:2,品牌:福特;在所有汽车上将这些相同的属性设置为不同的值。

直觉告诉我,最好在产品表中添加“颜色”、“门”和“制造”列。

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

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

这些方法有什么问题,任何人都可以为我推荐任何替代方案或阐明这个主题吗?

提前致谢

【问题讨论】:

    标签: sql database filter


    【解决方案1】:

    您应该阅读有关数据库规范化的信息。将串联字符串用作单个列中的值通常不是一个好主意。我做了一个很小的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"
    

    【讨论】:

    • 谢谢,我知道这是不好的做法,只需要指出正确的方向;我将阅读规范化并现在有一个小提琴:)
    • 如果我还需要那个 color=black AND doors=2 怎么办?那么查询会是什么样子?
    【解决方案2】:

    以后有人读到这篇文章,感谢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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-04
      • 2020-08-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多