2016-06-12 141 views
1

我有我的數據庫MySQL查詢和where子句

# Items 
id - name 
---------- 
1 - Item A 
2 - Item B 
3 - Item C 

3桌。

# Traits 
id - name 
---------- 
1 - Color 
2 - Grade 
3 - Size 

# Values 
id - item_id - trait_id - value 
---------- 
1 - 1 - 1 - red 
1 - 2 - 1 - green 
1 - 3 - 1 - red 
1 - 1 - 2 - 90% 
1 - 2 - 2 - 45% 
1 - 3 - 2 - 80% 
1 - 1 - 3 - 4 inches 
1 - 2 - 3 - 5 inches 
1 - 3 - 3 - 9 inches 

在Laravel,我能得到他們的特質和價值觀的所有項目使用「屬於關聯」 [$這個 - >屬於關聯(「應用程序\特質」,「trait_id」);在價值模型得到的結果像這樣:

--- Item A 
Color: red 
Grade: 90% 
Size: 4 inches 

--- Item B 
Color: green 
Grade: 45% 
Size: 5 inches 

.. etc 

從這樣的代碼:

$items = Items::get(); 
foreach ($items as $item) { 
    echo '<h2>'.$item->name.'</h2>'; 
    foreach ($item->values as $value) { 
     echo '<b>'.$value->trait->name . '</b>: '; 
     echo $value->value . '<br>'; 
    } 
} 

不過,我不能做的是,我需要過濾這些結果,爲例子,我只需要的項目,它的顏色是「紅色」及其等級大於70%?

如果你不使用Larave,隨時將它寫在純MySQL的查詢,我會找到一個方法來做到這一點在Laravel時,我的想法..謝謝你

+2

'id'供應中的值表中沒有目的(這是,順便說一句,一個糟糕的名字選擇)。如果使用EAV模型,一個好的提示是爲每個數據類型構建單獨的表。 – Strawberry

+0

@Strawberry其實這是我第一次瞭解EAV模型,上面的所有結構都來自我的頭部,對EAV沒有任何瞭解,我會詳細瞭解它,看看這種方法的最佳做法,謝謝提示 – Ahmad

回答

1

過濾項目/實體通過(多個)屬性值對是EAV model的缺點之一。有一些方法可以實現這一點。一是加入ItemsTraitsValues一旦每個條件:

select i.* 
from Items i 
join `Values` v1 on v1.item_id = i.id 
join `Values` v2 on v2.item_id = i.id 
join Traits t1 on t1.id = v1.trait_id 
join Traits t2 on t2.id = v2.trait_id 
where t1.name = 'Color' and v1.value = 'red' 
    and t2.name = 'Grade' and v2.value > 70 

sqlfiddle

您還可以使用旋轉來獲得與列(ITEM_ID,顏色,等級),其結果是:

select v.item_id 
    , max(case when t.name = 'Color' then v.value end) as Color 
    , max(case when t.name = 'Grade' then v.value end) as Grade 
from `Values` v 
join Traits t on t.id = v.trait_id 
group by v.item_id 
having Color = 'red' and Grade > 70 

此結果可以與Items表連接以獲取過濾的項目。的修改也可以在WHERE-IN的條件下使用:

select * from Items 
where id in (
    select v.item_id 
    from `Values` v 
    join Traits t on t.id = v.trait_id 
    group by v.item_id 
    having max(case when t.name = 'Color' then v.value end) = 'red' 
    and max(case when t.name = 'Grade' then v.value end) > 70 
); 

sqlfiddle

的另一種方法:

select * from Items 
where id in (
    select v.item_id 
    from `Values` v 
    join Traits t on t.id = v.trait_id 
    where t.name = 'Color' and v.value = 'red' 
    or t.name = 'Grade' and v.value > 70 
    group by v.item_id 
    having count(v.item_id) = 2 
); 
+0

謝謝非常保羅!第一次我知道EAV模型,我會詳細閱讀它。 – Ahmad