2010-10-07 28 views
1

我有一個關於通用數據庫結構的SQL相關問題,似乎有點常見。有一天,我試圖解決一個問題,並且(後來)我看到其他人做同樣的事情(或者非常相似的事情),所以我認爲結構本身是有意義的。我試圖對它進行某些查詢時遇到困難。如何在SQL數據庫中使用行作爲字段

這個想法是,你已經有一個表中的「項目」,並且你想存儲一組字段及其每個項目的值。通常這可以通過簡單地向列表添加列來完成,問題在於字段本身(而不僅僅是值)隨着項目的不同而不同。例如,我可能有兩個項目:


   的product_id = aproductid
    hidden_​​key = ahiddenkeyvalue
第2條
   的product_id = anotherproductid
   地址= anaddress

您可以看到這兩個項目都有一個product_id字段(具有不同的值),但是爲每個項目存儲的數據是不同的。

在數據庫中的結構最終是這樣的:

ItemsTable
    ID
    itemdata_1
    itemdata_2
    ...

FieldsTable
    ID
    FIELD_NAME
    ...

這涉及他們,使得它的工作

FieldsItemRelationsTable
    FIELD_ID
    ITEM_ID表
   值


那麼,當我試圖做一些只涉及一個「動態字段」值的東西時,就沒有問題了。我通常做類似的東西:

SELECT i.* FROM ItemsTable i 
INNER JOIN FieldsItemRelationsTable v ON v.item_id = i.id 
INNER JOIN FieldsTable f ON f.id = v.field_id 
WHERE v.value = 50 AND f.name = 'product_id'; 

它選擇的所有項目,其中的product_id = 50

,當我需要做的,涉及多個「動力場」的價值觀的東西,就會出現問題。假設我想選擇product_id = 50和hidden_​​key = 30的所有項目。是否可以使用單個SQL語句?我試過了:

SELECT i.* FROM ItemsTable i 
INNER JOIN FieldsItemRelationsTable v ON v.item_id = i.id 
INNER JOIN FieldsTable f ON f.id = v.field_id 
WHERE (v.value = 50 AND f.name = 'product_id') 
AND (v.value = 30 AND f.name = 'hidden_key'); 

但它只是返回零行。

+1

我添加了'eav'標籤。該設計被稱爲實體屬性值。 – 2011-07-22 18:56:50

回答

2

你需要做一個單獨的加入爲你帶回的每個值...

SELECT i.* FROM ItemsTable i 
INNER JOIN FieldsItemRelationsTable v ON v.item_id = i.id 
INNER JOIN FieldsTable f ON f.id = v.field_id 
INNER JOIN FieldsItemRelationsTable v2 ON v2.item_id = i.id 
INNER JOIN FieldsTable f2 ON f2.id = v2.field_id 
WHERE v.value = 50 AND f.name = 'product_id' 
AND (v2.value = 30 AND f2.name = 'hidden_key'); 

呃......查詢可能無法正常工作(上有點複製/粘貼污泥工作我的部分),但是你明白了......你需要第二個值在表格的第二個實例中(這裏是我的例子中的v2和f2),它比第一個實例分開。 v1.value = 30和v2.value = 50. v1.value = 50和v1.value = 30不應該返回行,因爲沒有什麼會等於30和50在同一時間

作爲一個後思... ...查詢可能會更容易閱讀了你把WHERE子句中的連接語句

SELECT i.* FROM ItemsTable i 
INNER JOIN FieldsItemRelationsTable v ON v.item_id = i.id and v.value = 50 
INNER JOIN FieldsTable f ON f.id = v.field_id and f.name = 'product_id' 
INNER JOIN FieldsItemRelationsTable v2 ON v2.item_id = i.id and v2.value = 30 
INNER JOIN FieldsTable f2 ON f2.id = v2.field_id and f2.name = 'hidden_key' 

功能這兩個查詢應雖然操作相同。我不確定是否有邏輯上的限制......在調度系統中,您經常會看到「異常」的設置...我有一個像這樣加入的報告查詢28​​次...每個異常都有一個鍵入返回。

+0

還有一條評論......你的例子與我以前看到的有點不同,因爲你有第三張表格來把這兩者聯繫起來。 item_id和item_detail表的item_id(fk到items),'item_details_code'(或item_detail_ID ...保持唯一的細節)和itemdetailtext列。具有與您在這裏相同的功能,只需少於一個表 – Twelfth 2010-10-07 19:55:44

+0

就是這樣!謝謝 – rushinge 2010-10-07 19:55:57

1

對不起,是模糊的,但我會調查你的選擇更多。

+0

我很欣賞這個輸入,而EAV絕對是我會閱讀更多內容的,但是對於這個特殊的解決方案,我必須堅持現在的數據庫安排。 – rushinge 2010-10-07 19:06:54

0

嘗試做一些左或右連接,看看你是否得到任何結果。如果有空字段,內部聯接有時不會返回結果。

它的一個開始。

不要忘記,外連接=笛卡爾產品

相關問題