标记系统的MySQL模式和CRUD查询

时间:2011-11-08 16:40:31

标签: mysql sql database schema relational-database

让我们想象一下,我有视频,每个视频都有几个标签(每个视频最多10个标签)。

我计划了我的SQL架构,它看起来像这样:

  • videosidtitlepath
  • tag_relsidtag_iditem_id(它会指向videosid),
  • tagsidtag;

好的,对我来说似乎很好。

然后我写了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中插入视频。这将返回主键(videosid),对吧?
  • 查询#2:从数据库中选择标记#1并获取它的主键
  • 查询#3:如果没有这样的记录(基于标记名称(tagstag),请执行插入查询并插入它。目标是获取主键标签
  • 查询#4:在tag_rels中插入带有视频 pk 和标签 pk 的条目;

因此,每个视频都是一个查询,加上每个标记的2或3个查询。

这意味着,如果视频有10个标签,并且(最糟糕的情况)这些标签中的任何一个都没有保存在数据库中,那将花费我1 + 10 * 3 ...... em .... 31查询?!

必须有更好的方法!非常感谢!

P.S。我不希望数据库中出现重复条目​​,我希望将used_in列添加到tags,其中包含使用该标记的视频计数。将来......

2 个答案:

答案 0 :(得分:2)

这看起来与存储过程类似。让商店制作视频数据和标签列表。然后在里面查询#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 :(得分:1)

我认为你的计算错了。无论标签号如何,您都需要执行3次查询 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.假设你有一个唯一的索引(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)