1

这个问题与这个问题相似,但有所不同:我有八种不同类型的标签。

像这样的东西:

videos      [id, title]
tags1       [id, tag]
tags2       [id, tag]
tags3       [id, tag]
tags4       [id, tag]
tags5       [id, tag]
tags6       [id, tag]
tags7       [id, tag]
tags8       [id, tag]
video_tags1 [vid_id, tag_id]
video_tags2 [vid_id, tag_id]
video_tags3 [vid_id, tag_id]
video_tags4 [vid_id, tag_id]
video_tags5 [vid_id, tag_id]
video_tags6 [vid_id, tag_id]
video_tags7 [vid_id, tag_id]
video_tags8 [vid_id, tag_id]

给定一个 video.id,我想根据哪些视频具有最多的共同标签来挑选相关视频。我发现很难找到一种方法来做到这一点,更不用说一种不会让服务器崩溃的方法了。

4

2 回答 2

2

如果您可以更改数据库模型,那么这些建议可能适合您。

以这种方式重新定义您的表格:

videos      [id, title]
tags    [id, tag_type,tag]
videos_tags [vid_id, tag_id]

您还可以添加一个 tag_type 表(它将有 8 行,每个标签类型一个)以获得更高的一致性。

然后这个查询(它可能有一些语法错误,但我的意图是你明白了)会给你视频ID和匹配标签的数量与提供的标签:

select 
       videos.id, count(videos.id) as nEqualTags 
from 
       videos videos inner join  video_tags vtags on  (vtags.vid_id=videos.id )
where 
       vtags.tag_id in (select tag_id from videos_tags where vt.id = ?) 
group by 
       videos.id 
order by 
       nEqualTags desc

nEqualTags如果低于某个值,您可以添加更多逻辑以减少结果。

(并且还考虑添加一些索引以获得更好的性能)。

希望能帮助到你

于 2012-11-07T16:39:28.363 回答
1

我认为处理规范化表总是一个好主意,在这种情况下,这个 UNION 查询可能会有所帮助:

(select 1 as tab, vid_id, tag_id from video_tags1
 union select 2 as tab, vid_id, tag_id from video_tags2
 union select 3 as tab, vid_id, tag_id from video_tags3
 ...)

现在你必须使用这样的查询:

SELECT
  tags_1.vid_id, count(*) as common_tags
FROM
  (big union above) video_tags
  INNER JOIN
  (big union above) video_tags_1
  ON video_tags.tab = video_tags_1.tab
  AND video_tags.tags_id = video_tags_1.tags_id
  AND video_tags.vid_id = 1
  AND video_tags_1.vid_id <> 1
GROUP BY video_tags_1.vid_id
ORDER BY common_tags DESC

这将返回所有按它们共有的标签数量排序的 DESC 记录。这可能是如何进行的想法。您应该再添加一个 JOIN 以获得视频的标题。如果您还需要获取它们共同的标签的描述......这是可能的,但我认为这会使查询复杂化很多!

你确定你不能改变你的数据库模型,只使用一个表作为标签,一个表作为视频标签吗?它会让事情变得容易得多!

于 2012-11-07T16:49:50.487 回答