Généralement, pour ce type de relation plusieurs-à-plusieurs, il existe trois tables :
- Le "
article
" tableau- clé primaire =identifiant
- La "
tag
" tableau- clé primaire =identifiant
- contient les données de chaque balise :
- nom, par exemple
- Un "
tags_articles
" table, qui agit comme une table de jointure, et contient uniquement :id_article
:clé étrangère qui pointe vers un articleid_tag
:clé étrangère qui pointe vers une balise
Ainsi, il n'y a aucune duplication des données d'un tag :pour chaque tag, il y a une et une seule ligne dans le tag
tableau.
Et, pour chaque article, vous pouvez avoir plusieurs balises (c'est-à-dire plusieurs lignes dans le champ tags_articles
table); et, bien sûr, pour chaque balise, vous pouvez avoir plusieurs articles.
Obtenir une liste de balises pour un article, avec cette idée, relève d'une requête supplémentaire, du type :
select tag.*
from tag
inner join tags_articles on tag.id = tags_articles.id_tag
where tags_articles.id_article = 123
Obtenir les trois articles "les plus similaires" signifierait :
- sélectionnez les articles qui ont des balises que le premier article a
- utiliser uniquement ceux qui ont le plus grand nombre de balises identiques
Pas testé, mais une idée pourrait être quelque chose qui ressemblerait à ceci :
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
En gros, vous :
- sélectionnez les identifiants d'articles pour chaque balise présente sur votre article initial
- comme il y a une jointure interne, si un article dans la base de données a 2 balises qui correspondent à
where
clause, sans legroup by
clause, il y aurait deux lignes pour cet article - Bien sûr, vous ne souhaitez pas sélectionner à nouveau l'article que vous aviez déjà, ce qui signifie qu'il doit être exclu.
- comme il y a une jointure interne, si un article dans la base de données a 2 balises qui correspondent à
- mais, comme vous utilisez
group by article.id
, il n'y aura qu'une seule ligne par article- mais vous pourrez utiliser
count
, pour savoir combien de tags chaque article a en commun avec le premier
- mais vous pourrez utiliser
- Ensuite, il suffit de trier par nombre de balises et d'obtenir uniquement les trois troisièmes lignes.