tags:

views:

186

answers:

3

I have a table that's holding metadata for entrys from another table. The metadata-table looks like this (I removed relating Ids so it's more obvious):

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

Now I want to search this table for the properties, like choosing all entries where color is blue:

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

So far, so good. But how do I expand the query when I have multiple conditions? For example I want to search for all entries where color is blue and shape is circle. Right now I'd achieve this with unions:

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

this obviously gets ugly the more properties I want to look for. And I think it's not very fast, too. Is there are more elegant way to do this? The reason for this table is, that I have objects with metadata which can be set by the user.

Thank you!

+1  A: 

is this what you're looking for?

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'
John Boker
I'd select DISTINCT entry_id's
Martijn
you would need to do select distinct, ID 12 would come back twice, his union statement is discarding the duplicate.
Andrew
i modified it so it'd select out what he asked for not what his previous query returned (hope this is what he wanted)
John Boker
thanks! I think I'll try it this way and make some perfomance tests with all the solutions provided
acme
A: 
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'
John Kugelman
Thanks, and does this perform well?
acme
@acme To get a godd performace, You have to create a index on (entry_id, property, value). If this triple isnt already a primary key.
Leonel Martins
A: 

You can trick MySQL into building a hash table in lieu of union or or:

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

You can also try an 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)

Using one of these two methods, you can append as many search conditions as your little heart desires by simply tacking on another union all to the s subquery.

Eric
thank you, are there any perfomance problems I can expect?
acme
and how can I achieve a "like" search on the fields with these meethods?
acme
These should actually be very performant. As for the `like`, you could do `where t.property like '%' + s.property + '%'` if you felt so inclined. It's just a join condition, so go nuts with it if you need to.
Eric