2009-08-14 77 views
1

我有一个表为其他表的entrys保存元数据。元数据表看起来像这样(我删除与ID,以便它更明显):MySQL:多次搜索单个表?

id entry_id property value
1 12 color blue
2 12 shape circle
3 13 color red
4 13 shape circle
5 14 color blue
6 14 shape square
7 15 material stone
8 12 material plastic

现在我要搜索此表的属性,如选择所有条目,其中颜色蓝色

select entry_id from table where property = 'color' and value = 'blue'

到目前为止,一切都很好。但是,如何在有多个条件时扩展查询?例如,我想搜索所有条目,其中颜色蓝色形状圈子。现在我想与工会实现这一目标:

select entry_id from table where property = 'color' and value = 'blue'
union
select entry_id from table where property = 'shape' and value = 'circle'

这显然变得丑陋了更多的属性我想看看。我认为这也不是很快。有没有更优雅的方式来做到这一点?这张表的原因是,我有对象与元数据可以由用户设置。

谢谢!

+0

要获得godd的性能,不管你采取什么解决方案,你必须创建一个索引(entry_id,property,value)。如果这个三元组不是主键。 – 2009-08-14 13:53:44

回答

1

这是你在找什么?

select 
    distinct e1.entry_id 
from 
table e1 
inner join 
    table e2 on e1.entry_id=e2.entry_id 
where 
    e1.property='color' and 
    e1.value='blue' and 
    e2.property='shape' and 
    e2.value='circle' 
+0

我会选择DISTINCT entry_id的 – Martijn 2009-08-14 13:13:16

+0

您需要做的选择不同,ID 12会回来两次,他的联合声明是放弃重复。 – Andrew 2009-08-14 13:13:29

+0

我修改它,所以它会选择他要求的不是他以前的查询返回(希望这是他想要的) – 2009-08-14 13:16:53

0
SELECT a.entry_id 
FROM table a INNER JOIN table b USING (entry_id) 
WHERE a.property = 'color' AND a.value = 'blue' 
    AND b.property = 'shape' AND b.value = 'circle' 
+0

谢谢,这是否表现良好? – acme 2009-08-14 13:42:27

+0

@acme要获得godd的性能,您必须在(entry_id,property,value)上创建一个索引。如果这个三元组不是主键。 – 2009-08-14 13:52:45

0

你就可以欺骗MySQL来代替unionor建立一个哈希表:

select distinct 
    entry_id 
from 
    table t 
    inner join 
     (select 'shape' as property, 'circle' as value 
     union all 
     select 'color' as property, 'blue' as value) s on 
     t.property = s.property 
     and t.value = s.value 

您也可以尝试exists:中

select distinct 
    entry_id 
from 
    table t 
where 
    exists (select 1 from 
       (select 'shape' as property, 'circle' as value 
       union all 
       select 'color' as property, 'blue' as value) s 
      where 
       s.property = t.property 
       and s.value = t.value) 

使用一个这两种方法,你可以追加尽可能多的搜索条件,因为你的小心脏需要简单地加上另一个union alls子查询。

+0

谢谢,我可以期待任何性能问题吗? – acme 2009-08-14 13:43:12

+0

以及如何使用这些方法在字段上实现“类似”搜索? – acme 2009-08-14 13:54:50

+0

这些应该是非常高效的。至于'like',如果你觉得这样倾向的话,你可以't.property'如'%'+ s.property +'%''。这只是一个连接条件,所以如果你需要的话,坚持下去。 – Eric 2009-08-14 14:22:33