sql >> Base de Datos >  >> RDS >> Mysql

¿Cómo diseñar una tabla MySql para una nube de etiquetas?

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ículo
    • id_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 el group 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.
  • 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
  • entonces, solo es cuestión de ordenar por número de etiquetas y obtener solo las tres terceras líneas.