Полагаю, вы найдете этот пост интересным: Теги: Схемы базы данных
Проблема: вы хотите иметь схему базы данных, где вы можете пометить
Закладка (или сообщение в блоге или что-то еще) с таким количеством тегов, как вы хотите.
Позже вы захотите выполнить запросы, чтобы ограничить закладки
объединение или пересечение тегов. Вы также хотите исключить (скажем, минус)
некоторые теги из результатов поиска.
«MySQLicious» решение
В этом решении схема имеет только одну таблицу, она денормализована. Этот тип называется «MySQLicious solution», потому что MySQLicious импортирует данные del.icio.us в таблицу с такой структурой.
Пересечение (И)
Запрос «search + webservice + semweb»:
SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
AND tags LIKE "%webservice%"
AND tags LIKE "%semweb%"
Союз (ИЛИ)
Запрос «search | webservice | semweb»:
SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
OR tags LIKE "%webservice%"
OR tags LIKE "%semweb%"
Минус
Запрос «search + webservice-semweb»
SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
AND tags LIKE "%webservice%"
AND tags NOT LIKE "%semweb%"
Решение "Scuttle"
Scuttle организует свои данные в две таблицы. Эта таблица «scCategories» является таблицей «tag» и имеет внешний ключ для таблицы «bookmark».
Пересечение (И)
Запрос на «закладку + веб-сервис + веб-сеть»:
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
Сначала выполняется поиск всех комбинаций закладка-тег, где тегом является «закладка», «веб-сервис» или «веб-сеть» (c.category IN («закладка», «веб-сервис», «веб-служба»)), затем просто учитываются закладки, в которых были найдены все три тега (HAVING COUNT (b.bId) = 3).
Союз (ИЛИ)
Запрос на «закладку | веб-сервис | semweb»:
Просто пропустите предложение HAVING, и вы получите union:
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», то есть: закладка И веб-сервис, а НЕ 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 приводит к запросу «bookmark | webservice-semweb».
«Toxi» решение
Toxi придумали структуру из трех столов. Посредством таблицы «tagmap» закладки и теги связаны с n-to-m. Каждый тег можно использовать вместе с разными закладками и наоборот. Эта DB-схема также используется WordPress.
Запросы такие же, как и в решении «scuttle».
Пересечение (И)
Запрос на «закладку + веб-сервис + веб-сеть»
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
Союз (ИЛИ)
Запрос на «закладку | веб-сервис | 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», то есть: закладка И веб-сервис, а НЕ 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 приводит к запросу «bookmark | webservice-semweb».