2016-07-05 2 views
0

У меня есть две таблицы, Event и EventTagSQL: Найти записи с соответствующими критериями в другой таблице

CREATE TABLE event (
    id INT PRIMARY KEY, 
    content TEXT 
) 

CREATE TABLE event_tag (
    event_id INT, 
    type VARCHAR(255), 
    value VARCHAR(255) 
) 

Каждое событие имеет ноль или более меток. Запрос Я хотел бы выразить в SQL является:

Дайте мне все Event (все столбцы таблицы), которые связаны с теги EventTag.type="foo" and EventTag.value="bar".

Это легко один критерий тега (например, с присоединиться и где, как ответил here), но как я могу решить ситуацию двух или более критериев? Итак: Дайте мне события со связанным тегом «foo» равным «bar» и (!) Тегу события «qux», равному «quux»? Я думал о присоединении к таблице тегов «n» раз, но я не уверен, что это хорошая идея.

+0

Какие СУБД вы используете? –

+0

Я использую H2 для тестирования и Postgres 9.1 в производстве. –

+0

Взгляните на [реляционное подразделение] (https://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/), ака " поставщик, который поставляет все детали ». SQL/postrgre не имеет оператора 'divide', вы должны подделывать его с другими операторами, не обязательно, как предлагает @TomH (но это хороший старт). – onedaywhen

ответ

2

Лучший способ решить эту проблему - не использовать модель базы данных EAV (Entity-Attribute-Value). Вы сталкиваетесь с первой проблемой, связанной с этим анти-шаблоном. Быстрый поиск Google на «модели EAV» должен выявить некоторые другие проблемы в магазине для вас, если вы решите не перепроектировать. Обычно ваша таблица Event должна иметь столбец для foo и столбец для qux.

Одно из возможных решений, которые вы можете использовать, если вы настаиваете (или вынуждены) идти по этому пути:

SELECT id, content 
FROM Event 
WHERE id IN 
(
    SELECT 
     E.id 
    FROM 
     Event E 
    INNER JOIN Event_Tag T ON 
     T.event_id = E.id AND 
     (
      (T.type = 'foo' AND T.value = 'bar') OR 
      (T.type = 'qux' AND T.value = 'quux') 
     ) 
    GROUP BY 
     E.id 
    HAVING 
     COUNT(*) = 2 
) 

Если вы кладете различные пары типа/значения во временную таблицу или КТР то вы можете указать JOIN, а не перечислять все пары, которые вы хотите. Однако этот синтаксис будет зависеть от вашей СУБД.

+0

Благодарим вас за то, что вы внимательно прочитали вопрос и даже предоставили рекомендации по улучшению модели данных. Никогда раньше не слышал об EAV, но я буду читать и перепроектировать. –

0

Select id from EVENT ev INNER JOIN EVENT_TAG et ON ev.id = et.event_ID WHERE et.type = 'foo' AND et.value = 'bar'

Очевидно, что вы можете поставить любую вещь, которую вы хотите в скобки, чтобы найти то, что когда-либо типа вы хотите.

+1

'bar' является значением, а не типом, – onedaywhen

+0

Исправлено, пропущено это – MageeWorld

0

использовать или операнд для нескольких случаев/критериев

SELECT * FROM Event e join Event_tag on e.eventId = et.eventtagid where ((EventTag.type="foo" and EventTag.value="bar") or (EventTag.type="po" and EventTag.value="yo")) 

или если значения является dyanmic, то в зависимости от языка программирования, что интерфейс SQL, вы можете написать запрос

Например, в Java I может сделать это, используя

SELECT * FROM Event e join Event_tag et on e.eventid = et.eventtagid where (EventTag.type=? and EventTag.value=?) 

Где я назначаю указанную выше строку SQL Query и задаю параметры для нее.

Смежные вопросы