2009-08-14 3 views
1

У меня есть таблица, в которой хранятся метаданные для записей из другой таблицы. Метаданные таблица выглядит следующим образом (я удалил относящийся Идентификаторы так что более очевидно):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

Чтобы получить божественную силу, не имеет значения, какое решение вы принимаете, вам нужно создать индекс (entry_id, property, value). Если эта тройка не является первичным ключом. –

ответ

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's – Martijn

+0

, вам нужно было бы выбрать выделение, ID 12 вернется дважды, его инструкция объединения отбрасывает дубликат. – Andrew

+0

Я изменил его, чтобы он выбрал то, что он просил, а не то, что его предыдущий запрос вернулся (надеюсь, это то, что он хотел) –

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

+0

@acme Чтобы получить действие godd, вам нужно создать индекс (entry_id, property, value). Если эта тройка не является первичным ключом. –

0

Вы можете обмануть MySQL в построении хеш-таблицы вместо union или 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 

Вы также можете попробовать 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 all к подзапросу s.

+0

спасибо, есть ли какие-либо проблемы с производительностью, которые я могу ожидать? – acme

+0

и как я могу добиться «подобного» поиска по полям с этими методами? – acme

+0

Они должны быть очень эффективными. Что касается 'like', вы можете сделать' where t.property like '%' + s.property + '%' ', если вы так наклонены. Это просто условие соединения, поэтому сходите с ним, если вам нужно. – Eric