2013-05-03 77 views
0

我有一個我想按任意類別篩選的產品數據庫。假設我爲了一個例子運行一個車庫。我有一部分產品是汽車。SQL按屬性篩選(設計)

每輛車應該有一個屬性的集合,所有的汽車都有相同數量和類型的屬性;比如顏色:紅色,門:2,make:ford;在所有汽車上將這些相同的屬性設置爲不同的值。

直覺告訴我,最好在產品表中添加「顏色」,「門」和「製造」列。

但是:並非表中的所有產品都是汽車。也許我想在汽車的頁面上列出輪胎。顯然,「顏色」和「門」不適用於輪胎。即便如此,如果用戶選擇color = red作爲過濾器,我仍然會因爲缺少顏色屬性而顯示輪胎。我認爲有一個「屬性」列,我可以填充任意數量的任意命名的屬性,然後使用SQL字符串函數進行過濾。如果你仔細計劃,我想你甚至可以在這裏使用一個位域。這對我來說似乎很難受,但我很想知道像亞馬遜這樣的一些大型網站如何做到這一點。

這些方法有哪些問題,任何人都可以推薦任何替代方案或爲我介紹這個主題?

在此先感謝

回答

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" 
+0

謝謝,我知道這是不好的做法只需要指向正確的方向;我會閱讀規範化,現在有小提琴:) – Pez 2013-05-03 09:39:55

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