Esquema MySQL y consultas CRUD para el sistema de etiquetas

Imaginemos que tengo videos y cada video puede tener pocas etiquetas (el máximo es 10 etiquetas por video).

Planeé mi esquema SQL y se ve así:

  • videos: id, title, path,
  • tag_rels: id, tag_id, item_id (apuntará a videos.id),
  • tags: id, tag;

Está bien, me parece bien.

Entonces escribí SELECT que debería incluir un video, además de etiquetas.

SELECT `videos`.`id`, `videos`.`title`, `videos`.`path`, `tags`.`tag`
FROM `videos`
JOIN `tag_rels`
    ON `tag_rels`.`item_id` = `videos`.`id`
JOIN `tags`
    ON `tags`.`id` = `tag_rels`.`tag_id`

No está probado o así porque todo está en el nivel de la mente.

En los gran problema is INSERT consulta (consultas, supongo).

Por lo que entiendo:

  • Consulta n. ° 1: insertar video en videos. Esto devolverá la clave principal (videos.id), ¿derecho?
  • Consulta n. ° 2: seleccione la etiqueta n. ° 1 de la base de datos y obtenga su clave principal,
  • Consulta n. ° 3: si no existe tal registro (según el nombre de la etiqueta (tags.tag), haga una consulta de inserción e insértela. El objetivo es obtener la clave principal de esa etiqueta,
  • Consulta n. ° 4: inserte la entrada en tag_rels con videos pk y la etiqueta pk;

Por lo tanto, es una consulta por video tal como está, más 2 o 3 consultas para cada etiqueta.

Esto significa que si el video tiene 10 etiquetas y (en el peor de los casos) alguna de esas etiquetas no se guarda en la base de datos, me costará 1 + 10 * 3 ... em ... ¡¿31 consultas ?!

¡Tiene que haber una manera mejor! ¡Muchas gracias!

PD: no quiero entradas duplicadas en la base de datos y me encantaría tener una columna used_in a tags con recuento de videos que usan la etiqueta. En el futuro...

preguntado el 08 de noviembre de 11 a las 16:11

2 Respuestas

Este es un caso similar para el procedimiento almacenado. Haga que los productos de la tienda tomen los datos del video y la lista de etiquetas. Luego haga las Consultas # 1 a # 4 adentro. Será mucho más rápido ya que no tiene que mover datos de un lado a otro.

Esto es lo que necesitaría. Es solo un punto de partida, así que no espere que se compile y mucho menos se ejecute correctamente, y necesitaría las 10 etiquetas (no creo que mysql pueda tomar una matriz, pero alguien podría saberlo mejor).

CREATE PROCEDURE insertvideo (IN videotitle CHAR(20),IN videopath CHAR(20), IN tag1 CHAR(20),IN tag2 CHAR(20), IN tag3 CHAR(20)  )
    BEGIN
      DECLARE myid INT;
      DECLARE tagid INT;
      INSERT INTO videos (title, path) VALUES ( videotitle,videopath);
      SELECT id INTO myid FROM videos WHERE title=videotitle AND path=videopath;
      SET tagid=NULL;
      SELECT id INTO tagid FROM tags WHERE tag=tag1;
      IF tagid IS NULL THEN
        INSERT INTO tags (tag) VALUES (tag1);
        SELECT id INTO tagid FROM tags WHERE tag=tag1;
      END IF;
      INSERT INTO tag_rels (tag_id, item_id) VALUES (tagid,myid);
      SET tagid=NULL;
      SELECT id INTO tagid FROM tags WHERE tag=tag2;
      IF tagid IS NULL THEN
        INSERT INTO tags (tag) VALUES (tag1);
        SELECT id INTO tagid FROM tags WHERE tag=tag2;
      END IF;
      INSERT INTO tag_rels (tag_id, item_id) VALUES (tagid,myid);
      SET tagid=NULL;
      SELECT id INTO tagid FROM tags WHERE tag=tag3;
      IF tagid IS NULL THEN
        INSERT INTO tags (tag) VALUES (tag1);
        SELECT id INTO tagid FROM tags WHERE tag=tag3;
      END IF;
      INSERT INTO tag_rels (tag_id, item_id) VALUES (tagid,myid);
    END 

respondido 08 nov., 11:22

¿Puedes darme un ejemplo de eso? No tengo idea de cómo funcionan los procedimientos, nunca los usé antes. O, al menos, algunos enlaces ... - daGrevis

Creo que tu cálculo está mal. Deberá ejecutar 3 consultas independientemente del número de etiquetas.
1. INSERT INTO Video ...
2. INSERT INTO tags(tag)
SELECT * FROM
(SELECT 'tag_1' as tag UNION SELECT 'tag_2' ...)a WHERE NOT EXISTS (SELECT 1 FROM tags b WHERE b.tag = a.tag)

3.Suponiendo que tiene un índice único en (tag_id, item_id), INSERT IGNORE INTO tag_rels( tag_id, item_id) SELECT tag_id, new_video_id FROM tags WHERE tags.tag IN ([new tag_list]) (new_video_id - es Video.id que obtuvo después de insertar un registro en el video)

respondido 08 nov., 11:21

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.