Ответ 1
Я считаю, что вы найдете интересный этот пост в блоге: Теги: схемы базы данных
Проблема: вы хотите иметь схему базы данных, где вы можете пометить закладки (или сообщение в блоге или что-то еще) с таким количеством тегов, которое вы хотите. Позже вы хотите запускать запросы, чтобы ограничить закладки объединение или пересечение тегов. Вы также хотите исключить (скажем: минус) некоторые теги из результата поиска.
"MySQLicious" решение
В этом решении схема имеет только одну таблицу, она денормализуется. Этот тип называется "MySQLicious solution", потому что MySQL.com импортирует данные del.icio.us в таблицу с этой структурой.
Пересечение (AND) Запрос для "search + webservice + semweb":
SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
AND tags LIKE "%webservice%"
AND tags LIKE "%semweb%"
Союз (OR) Запрос для "search | webservice | semweb":
SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
OR tags LIKE "%webservice%"
OR tags LIKE "%semweb%"
Минус Запрос для поиска "web-сервис-semweb"
SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
AND tags LIKE "%webservice%"
AND tags NOT LIKE "%semweb%"
Решение "Scuttle"
Scuttle организует свои данные в двух таблицах. Эта таблица "scCategories" является "tag" -table и имеет внешний ключ для "закладки" -table.
Пересечение (AND) Запрос для "bookmark + webservice + semweb":
SELECT b.*
FROM scBookmarks b, scCategories c
WHERE c.bId = b.bId
AND (c.category IN ('bookmark', 'webservice', 'semweb'))
GROUP BY b.bId
HAVING COUNT( b.bId )=3
Сначала выполняется поиск всех комбинаций меток-меток, где тегом являются "bookmark", "webservice" или "semweb" (c.category IN ( "bookmark", "webservice", "semweb" )), а затем просто учитываются закладки, у которых есть все три найденных тэга (HAVING COUNT (b.bId) = 3).
Союз (OR) Запрос для "закладки | webservice | semweb": Просто оставьте предложение HAVING, и у вас есть союз:
SELECT b.*
FROM scBookmarks b, scCategories c
WHERE c.bId = b.bId
AND (c.category IN ('bookmark', 'webservice', 'semweb'))
GROUP BY b.bId
Минус (исключение) Запрос для "bookmark + webservice-semweb", то есть: bookmark И webservice И НЕ semweb.
SELECT b. *
FROM scBookmarks b, scCategories c
WHERE b.bId = c.bId
AND (c.category IN ('bookmark', 'webservice'))
AND b.bId NOT
IN (SELECT b.bId FROM scBookmarks b, scCategories c WHERE b.bId = c.bId AND c.category = 'semweb')
GROUP BY b.bId
HAVING COUNT( b.bId ) =2
Оставив HAVING COUNT, вы получите запрос на "закладку | webservice-semweb".
Решение "Токси"
Toxi придумал структуру из трех таблиц. Через таблицу "tagmap" закладки и теги связаны с n-to-m. Каждый тег можно использовать вместе с разными закладками и наоборот. Эта DB-схема также используется wordpress. Запросы совершенно такие же, как в решении "scuttle".
Пересечение (AND) Запрос для "bookmark + webservice + semweb"
SELECT b.*
FROM tagmap bt, bookmark b, tag t
WHERE bt.tag_id = t.tag_id
AND (t.name IN ('bookmark', 'webservice', 'semweb'))
AND b.id = bt.bookmark_id
GROUP BY b.id
HAVING COUNT( b.id )=3
Союз (OR) Запрос для "закладки | webservice | semweb"
SELECT b.*
FROM tagmap bt, bookmark b, tag t
WHERE bt.tag_id = t.tag_id
AND (t.name IN ('bookmark', 'webservice', 'semweb'))
AND b.id = bt.bookmark_id
GROUP BY b.id
Минус (исключение) Запрос для "bookmark + webservice-semweb", то есть: bookmark И webservice И НЕ semweb.
SELECT b. *
FROM bookmark b, tagmap bt, tag t
WHERE b.id = bt.bookmark_id
AND bt.tag_id = t.tag_id
AND (t.name IN ('Programming', 'Algorithms'))
AND b.id NOT IN (SELECT b.id FROM bookmark b, tagmap bt, tag t WHERE b.id = bt.bookmark_id AND bt.tag_id = t.tag_id AND t.name = 'Python')
GROUP BY b.id
HAVING COUNT( b.id ) =2
Оставив HAVING COUNT, вы получите запрос на "закладку | webservice-semweb".