Я вірю, що ця публікація в блозі вам стане цікавою: Теги: Схеми баз даних
Проблема: Ви хочете мати схему бази даних, де ви можете позначити закладку (або допис у блозі чи що завгодно) такою кількістю тегів, скільки хочете. Пізніше ви захочете запустити запити, щоб обмежити закладки об'єднанням або перетином тегів. Ви також хочете виключити (скажімо: мінус) деякі теги з результату пошуку.
Рішення “MySQLicious”
У цьому рішенні схема має лише одну таблицю, вона денормалізована. Цей тип називається «рішення MySQLicious», оскільки MySQLicious імпортує дані del.icio.us до таблиці з цією структурою.
Запит на перетин (І) для “пошук + веб-сервіс + напівавтоматична мережа”:
SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
AND tags LIKE "%webservice%"
AND tags LIKE "%semweb%"
Запит на об'єднання (АБО) "пошук | веб-служба | semweb":
SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
OR tags LIKE "%webservice%"
OR tags LIKE "%semweb%"
Мінус запит для "пошук + веб-сервіс-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
Спочатку здійснюється пошук усіх комбінацій закладки та тегу, де тегом є «закладка», «веб-служба» або «semweb» (c.category IN («закладка», «веб-служба», «semweb»)), потім лише закладки, які отримали, що всі три пошукові теги враховані (МАЮЧИ КІЛЬКІ (b.bId) = 3)
Запит на об'єднання (АБО) для "закладки | веб-сервіс | 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
Мінус (виключення) Запит для “закладки + веб-сервіс-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” закладки та теги пов’язані між собою. Кожен тег можна використовувати разом із різними закладками та навпаки. Цю схему DB також використовує wordpress. Запити цілком такі ж, як і у "розмиті" рішення.
Запит на перетин (І) для “закладки + веб-сервіс + напівавтоматична мережа”
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
Мінус (виключення) Запит для “закладки + веб-сервіс-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”.