Mysql查询来自3个表和where子句

时间:2016-06-12 18:30:11

标签: php mysql laravel

我的数据库中有3个表

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

# 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中,我可以使用" belongsTo"来获取所有具有其特征和价值的项目。 [$ this-> belongsTo(' App \ Traits',' trait_id');]在Value模型中获得如下结果:

--- 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>';
  }
}

然而,我无法做的是我需要过滤这些结果,例如,我只需要其颜色为&#34;红色&#34;它的等级大于70%?

如果您不使用Larave,请随意在纯粹的mysql查询中编写它,当我得到这个想法时,我可能会在Laravel中找到一种方法...谢谢

1 个答案:

答案 0 :(得分:1)

按(多个)属性 - 值对过滤项目/实体是EAV model的缺点之一。有一些方法可以实现这一目标。一种是每个条件加入Items表格TraitsValues

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,Color,Grade):

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
);