MySQL, присоединиться и исключить совпадения - PullRequest
2 голосов
/ 01 февраля 2011

У меня есть система, которая позволяет мне работать с книгами, и исследования, которые могут проводить люди, когда ищут книги.

База данных mysql, и у меня есть две основные таблицы BOOKS и RESEARCHES.

BOOKS(id *int*, author *string*, title *string*, price *string*, tags *set('sci-fi', 'literature', 'theatre', 'drama', 'romance', 'recent', ...)*, ...) 

RESEARCHES is (researches_id, price_max, author, ...)

Когда я добавляю книгу в свою базу данных, я хочу получить исследования, соответствующие этой новой книге.Поскольку люди могут использовать много тегов в своих исследованиях (более 30), я решил создать другую таблицу, а не использовать столбец тегов в RESEARCHES, который был бы SET, потому что я считаю, что нет индекса настолбец SET, и поэтому моя база данных не может быстро обработать мой запрос.

RESEARCHES_TAGS(id, researches_id, tag).

Если я добавлю книгу П.К. Дика с тегами 'sci-fi', 'drama', я хочу получить исследования с тегом NULL или тегом ('scifi ',' drama ') и исключить исследования с другими тегами.

Итак, я делаю следующий запрос:

SELECT * FROM RESEARCHES
LEFT JOIN RESEARCHES_TAGS ON RESEARCHES.researches_id = RESEARCHES_TAGS.researches_id AND RESEARCHES_TAG.tag IN ('literature', 'theatre', 'romance', ...)
WHERE RESEARCHES_TAGS.tag IS NULL

Обратите внимание, что указанный массив тегов не содержиттэги 'научная фантастика', 'драма'.

Мой вопрос: есть ли лучшее решение?

Ответы [ 2 ]

1 голос
/ 01 февраля 2011

Я думаю, что смысл состоит в том, чтобы исключить строки, связанные с тегами "литература", "театр", "романтика" и т. Д., И сохранять только строки без критериев или с соответствующими критериями (научно-фантастическиеили драма или оба).Запрос, который вы предлагаете, выполняет противоположное действие.

Я сам обычно использую оператор LEFT JOIN j WHERE j.id IS NULL, но это, очевидно, нелогичное решение.

Возможно, переопределение структуры таблиц позволило бы упроститьи / или более быстрый запрос?Давайте перефразируем проблему ...

Will asks for any products
Jane asks for products with at least A and B
John asks for products with at least C
Yael asks for products with at least A and C
Mark asks for products with at least A

У вас есть продукт, который соответствует требованиям A и B.Кому вы продаете это?

Ответ: Уилл, Джейн и Марк, как вы поместите это в таблицы и запрос?

Если у вас есть только несколько типов требований, выпоставьте поле для каждого и попросите WHERE C = 0 AND D = 0, потому что вы не хотите связываться с людьми, которым требуется то, чего у вас нет.Но что, если у вас есть растущий список критериев?Вы не можете просто продолжать добавлять поля.А использование заданного поля исключает возможность работы с индексом.

0 голосов
/ 01 февраля 2011

Вы должны хранить свои критерии JOIN отдельно от критериев WHERE. Кроме того, INNER JOIN имеет для меня больше смысла, так как у вас не будет строки RESEARCHES_TAGS без соответствующей строки RESEARCHES ... верно?

SELECT * FROM RESEARCHES
INNER JOIN RESEARCHES_TAGS ON RESEARCHES.researches_id = RESEARCHES_TAGS.researches_id 
WHERE RESEARCHES_TAGS.tag IS NULL OR tag IN ('literature', 'theatre', 'romance', ...)

Также ... вы должны уточнить этот запрос, чтобы указать, к какой таблице tag принадлежит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...