Myślę, że ten post na blogu będzie interesujący: Tagi: Schematy baz danych
Problem: Chcesz mieć schemat bazy danych, w którym możesz oznaczyć zakładkę (lub post na blogu lub cokolwiek innego) dowolną liczbą tagów. Później chcesz uruchamiać zapytania, aby ograniczyć zakładki do unii lub przecięcia znaczników. Chcesz także wykluczyć (powiedzmy: minus) niektóre tagi z wyników wyszukiwania.
Rozwiązanie „MySQLicious”
W tym rozwiązaniu schemat ma tylko jedną tabelę, jest on zdenormalizowany. Ten typ jest nazywany „rozwiązaniem MySQLicious”, ponieważ MySQLicious importuje dane del.icio.us do tabeli o takiej strukturze.
Zapytanie o skrzyżowanie (AND) dla „search + webservice + semweb”:
SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
AND tags LIKE "%webservice%"
AND tags LIKE "%semweb%"
Zapytanie Union (OR) dla „search | webservice | semweb”:
SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
OR tags LIKE "%webservice%"
OR tags LIKE "%semweb%"
Zapytanie minus dla „search + webservice-semweb”
SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
AND tags LIKE "%webservice%"
AND tags NOT LIKE "%semweb%"
Rozwiązanie „Scuttle”
Scuttle organizuje swoje dane w dwóch tabelach. Ta tabela „scCategories” jest tabelą „tagów” i ma klucz obcy do tabeli „zakładek”.
Zapytanie o skrzyżowanie (AND) dla „zakładka + usługa internetowa + 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
Najpierw przeszukiwane są wszystkie kombinacje zakładka-znacznik, gdzie tag to „zakładka”, „usługa sieciowa” lub „semweb” (c.category IN („bookmark”, „webservice”, „semweb”)), a następnie tylko zakładki, które uwzględniono wszystkie trzy wyszukiwane tagi (HAVING COUNT (b.bId) = 3).
Zapytanie Union (OR) dla „bookmark | webservice | semweb”:
Po prostu pomiń klauzulę HAVING i masz union:
SELECT b.*
FROM scBookmarks b, scCategories c
WHERE c.bId = b.bId
AND (c.category IN ('bookmark', 'webservice', 'semweb'))
GROUP BY b.bId
Minus (wykluczenie) Zapytanie dla „bookmark + webservice-semweb”, czyli: bookmark AND webservice AND NOT 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
Pominięcie opcji HAVING COUNT prowadzi do zapytania „bookmark | webservice-semweb”.
Rozwiązanie „Toxi”
Toxi wymyślił strukturę z trzema stołami. Za pomocą tabeli „tagmap” zakładki i znaczniki są powiązane n-to-m. Każdy tag może być używany razem z różnymi zakładkami i odwrotnie. Ten schemat DB jest również używany przez wordpress. Zapytania są takie same, jak w przypadku rozwiązania „scuttle”.
Zapytanie o skrzyżowanie (AND) dla „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
Zapytanie Union (OR) dla „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
Minus (wykluczenie) Zapytanie dla „bookmark + webservice-semweb”, czyli: bookmark AND webservice AND NOT 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
Pominięcie opcji HAVING COUNT prowadzi do zapytania „bookmark | webservice-semweb”.