Credo che troverai interessante questo post del blog: Tag: Schemi di database
Il problema: vuoi avere uno schema di database in cui puoi taggare un segnalibro (o un post di blog o qualsiasi altra cosa) con tutti i tag che desideri. Successivamente, si desidera eseguire query per vincolare i segnalibri a un'unione o intersezione di tag. Vuoi anche escludere (ad esempio: meno) alcuni tag dal risultato della ricerca.
Soluzione "MySQLicious"
In questa soluzione, lo schema ha una sola tabella, viene denormalizzato. Questo tipo è chiamato "soluzione MySQLicious" perché MySQLicious importa i dati del.icio.us in una tabella con questa struttura.
Intersezione (AND) Query per "ricerca + servizio web + semweb":
SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
AND tags LIKE "%webservice%"
AND tags LIKE "%semweb%"
Query Union (OR) per "ricerca | webservice | semweb":
SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
OR tags LIKE "%webservice%"
OR tags LIKE "%semweb%"
Query meno per "ricerca + webservice-semweb"
SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
AND tags LIKE "%webservice%"
AND tags NOT LIKE "%semweb%"
Soluzione "Scuttle"
Scuttle organizza i suoi dati in due tabelle. La tabella "scCategories" è la tabella "tag" e ha una chiave esterna per la tabella "segnalibro".
Intersezione (AND) Query per "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
Innanzitutto, vengono cercate tutte le combinazioni di tag segnalibro, dove il tag è "segnalibro", "webservice" o "semweb" (c.category IN ('bookmark', 'webservice', 'semweb')), quindi solo i segnalibri che sono stati presi in considerazione tutti e tre i tag cercati (HAVING COUNT (b.bId) = 3).
Union (OR) Query per "bookmark | webservice | semweb":
basta lasciare fuori la clausola HAVING e hai l'unione:
SELECT b.*
FROM scBookmarks b, scCategories c
WHERE c.bId = b.bId
AND (c.category IN ('bookmark', 'webservice', 'semweb'))
GROUP BY b.bId
Meno (Esclusione) Query per "bookmark + webservice-semweb", ovvero: bookmark AND webservice E NON 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
Tralasciando HAVING COUNT porta alla Query per "bookmark | webservice-semweb".
Soluzione "Toxi"
Toxi ha inventato una struttura a tre tavoli. Tramite la tabella "tagmap" i segnalibri e i tag sono correlati da n a m. Ogni tag può essere utilizzato insieme a diversi segnalibri e viceversa. Questo schema DB viene utilizzato anche da wordpress. Le query sono quasi le stesse della soluzione "scuttle".
Intersezione (AND) Query per "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
Query dell'Unione (OR) per "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
Meno (Esclusione) Query per "bookmark + webservice-semweb", ovvero: bookmark AND webservice E NON 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
Tralasciando HAVING COUNT porta alla Query per "bookmark | webservice-semweb".