In genere, per questo tipo di relazione molti-a-molti, ci sono tre tabelle:
- L'"
article
" tabella- chiave primaria =id
- Il "
tag
" tabella- chiave primaria =id
- contiene i dati di ogni tag :
- nome, per esempio
- Un "
tags_articles
" table, che funge da tabella di join e contiene solo :id_article
:chiave esterna che punta a un articoloid_tag
:chiave esterna che punta a un tag
In questo modo, non c'è duplicazione dei dati di alcun tag:per ogni tag, c'è una, e solo una, riga nel tag
tabella.
E, per ogni articolo, puoi avere più tag (cioè più righe nel tags_articles
tavolo); e, ovviamente, per ogni tag, puoi avere più articoli.
Ottenere un elenco di tag per un articolo, con questa idea, è una questione di query aggiuntiva, come :
select tag.*
from tag
inner join tags_articles on tag.id = tags_articles.id_tag
where tags_articles.id_article = 123
Ottenere i tre articoli "più simili" significherebbe:
- seleziona gli articoli che hanno i tag del primo articolo
- Utilizza solo quelli che hanno il numero più importante di tag identici
Non testato, ma un'idea potrebbe essere simile a questa :
select article.id, count(*) as nb_identical_tags
from article
inner join tags_articles on tags_articles.id_article = article.id
inner join tag on tag.id = tags_articles.id_tag
where tag.name in ('php', 'mysql', 'erlang')
and article.id <> 123
group by article.id
order by count(*) desc
limit 3
Fondamentalmente, tu :
- seleziona gli ID degli articoli per ogni tag presente nel tuo articolo iniziale
- poiché c'è un inner join, se un articolo nel DB ha 2 tag che corrispondono a
where
clausola, senza ilgroup by
clausola, ci sarebbero due righe per quell'articolo - ovviamente, non vuoi riselezionare l'articolo che avevi già, il che significa che deve essere escluso.
- poiché c'è un inner join, se un articolo nel DB ha 2 tag che corrispondono a
- ma, poiché usi
group by article.id
, ci sarà solo una riga per articolo- ma potrai usare
count
, per scoprire quanti tag ha in comune ogni articolo con quello iniziale
- ma potrai usare
- poi, è solo questione di ordinare per numero di tag e ottenere solo le terze tre righe.