Geralmente, para esse tipo de relacionamento muitos-para-muitos, existem três tabelas:
- O "
article
" mesa- chave primária =código
- A "
tag
" mesa- chave primária =código
- contém os dados de cada tag:
- nome, por exemplo
- Um "
tags_articles
" table, que atua como uma tabela de junção e contém apenas :id_article
:chave estrangeira que aponta para um artigoid_tag
:chave estrangeira que aponta para uma tag
Dessa forma, não há duplicação de dados de nenhuma tag:para cada tag, há uma, e apenas uma, linha na
tag
tabela. E, para cada artigo, você pode ter várias tags (ou seja, várias linhas no
tags_articles
tabela); e, claro, para cada tag, você pode ter vários artigos. Obter uma lista de tags para um artigo, com essa ideia, é uma questão de consulta adicional, como:
select tag.*
from tag
inner join tags_articles on tag.id = tags_articles.id_tag
where tags_articles.id_article = 123
Receber os três artigos "mais semelhantes" significaria:
- selecione artigos que tenham tags que o primeiro artigo tem
- use apenas aqueles que têm o número mais importante de tags idênticas
Não testado, mas uma ideia pode ser algo parecido com isto:
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
Basicamente, você:
- selecione os IDs dos artigos para cada tag presente em seu artigo inicial
- como há uma junção interna, se um artigo no banco de dados tiver 2 tags que correspondam ao
where
cláusula, sem ogroup by
cláusula, haveria duas linhas para esse artigo - claro, você não deseja selecionar novamente o artigo que já possuía -- o que significa que ele deve ser excluído.
- como há uma junção interna, se um artigo no banco de dados tiver 2 tags que correspondam ao
- mas, como você usa
group by article.id
, haverá apenas uma linha por artigo- mas você poderá usar
count
, para descobrir quantas tags cada artigo tem em comum com o inicial
- mas você poderá usar
- então, é apenas uma questão de classificar por número de tags e obter apenas as três terceiras linhas.