MySQL схема и CRUD запросы для системы тегов - PullRequest
0 голосов
/ 08 ноября 2011

Давайте представим, что у меня есть видео, и каждое видео может иметь несколько тегов (максимум 10 тегов на видео).

Я спланировал свою схему SQL, и она выглядит так:

  • videos: id, title, path,
  • tag_rels: id, tag_id, item_id (это будет указывать на videos. id),
  • tags: id, tag;

Хорошо, мне кажется, хорошо.

Тогда я написал SELECT, который должен получить видео плюс теги для него.

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`

Это не проверено или около того, потому что все на уровне ума.

И огромная проблема - это запрос INSERT (запросы, я думаю).

Насколько я понимаю:

  • Запрос № 1: вставить видео в videos. Это вернет первичный ключ (videos. id), верно?
  • Запрос # 2: выберите тег # 1 из базы данных и получите его первичный ключ,
  • Запрос № 3: если такой записи нет (на основе имени тега (tags. tag), выполните запрос вставки и вставьте его. Цель - получить первичный ключ этого тега,
  • Запрос # 4: вставить запись в tag_rels с видео pk и тегами pk ;

Итак, это один запрос на видео как есть, плюс 2 или 3 запроса для каждого тега .

Это означает, что если видео содержит 10 тегов и (в худшем случае) любой из этих тегов не сохраняется в базе данных, это будет стоить мне 1 + 10 * 3 ... em .... 31 запрос?!

Должен быть лучший способ! Большое спасибо!

P.S. Я не хочу повторяющихся записей в базе данных, и я хотел бы иметь столбец от used_in до tags с количеством видео, которые используют тег. В будущем ...

Ответы [ 2 ]

2 голосов
/ 08 ноября 2011

Это похоже на случай хранимой процедуры. Попросите магазин изготовить видео данные и список тегов. Затем выполните запросы с 1 по 4 внутри. Это будет намного быстрее, поскольку вам не нужно перемещать данные назад и вперед.

Вот то, что вам нужно. Это только отправная точка, поэтому не ожидайте, что она будет скомпилирована намного меньше, и вам понадобятся все 10 тегов (я не думаю, что mysql может взять массив, но кто-то может знать лучше).

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 
1 голос
/ 08 ноября 2011

Я думаю, что ваш расчет неверен.Вам нужно будет выполнить 3 запроса независимо от количества тегов.
1. INSERT INTO Video ...
2. INSERT INTO tags(tag)<br> SELECT * FROM<br> (SELECT 'tag_1' as tag UNION SELECT 'tag_2' ...)a WHERE NOT EXISTS (SELECT 1 FROM tags b WHERE b.tag = a.tag)
3. При условии, что у вас есть уникальный индекс (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 - это Video.id, который вы получили после вставки записи в видео)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...