Generalmente, para este tipo de relación de muchos a muchos, hay tres tablas:
- El "
article
" tabla- clave principal =id
- La "
tag
" tabla- clave principal =id
- contiene los datos de cada etiqueta :
- nombre, por ejemplo
- Un "
tags_articles
" table, que actúa como una tabla de combinación y contiene solo :id_article
:clave externa que apunta a un artículoid_tag
:clave externa que apunta a una etiqueta
De esta manera, no hay duplicación de los datos de ninguna etiqueta:para cada etiqueta, hay una, y solo una, línea en la tag
mesa.
Y, para cada artículo, puede tener varias etiquetas (es decir, varias líneas en el tags_articles
mesa); y, por supuesto, para cada etiqueta, puede tener varios artículos.
Obtener una lista de etiquetas para un artículo, con esta idea, es cuestión de una consulta adicional, como:
select tag.*
from tag
inner join tags_articles on tag.id = tags_articles.id_tag
where tags_articles.id_article = 123
Obtener los tres artículos "más similares" significaría:
- seleccione artículos que tengan etiquetas que tiene el primer artículo
- utilice solo aquellos que tengan la mayor cantidad de etiquetas idénticas
No probado, pero una idea podría ser algo como esto:
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
Básicamente, tú:
- seleccione los ID de artículos para cada etiqueta que está presente en su artículo inicial
- como hay una combinación interna, si un artículo en la base de datos tiene 2 etiquetas que coinciden con el
where
cláusula, sin elgroup by
cláusula, habría dos líneas para ese artículo - por supuesto, no desea volver a seleccionar el artículo que ya tenía, lo que significa que debe excluirse.
- como hay una combinación interna, si un artículo en la base de datos tiene 2 etiquetas que coinciden con el
- pero, al usar
group by article.id
, solo habrá una línea por artículo- pero podrá usar
count
, para saber cuántas etiquetas tiene cada artículo en común con el inicial
- pero podrá usar
- entonces, solo es cuestión de ordenar por número de etiquetas y obtener solo las tres terceras líneas.