我有一个小网站,我希望在标签的基础上获得相关视频...什么可能是最好的MS SQL 2005查询,以获得基于标签的相关视频。如果你能给出很棒的LINQ查询。
这是数据库架构:
CREATE TABLE Videos
(VideoID bigint not null ,
Title varchar(100) NULL,
Tags varchar(MAX) NULL,
isActive bit NULL )
INSERT INTO Videos VALUES ( 1,'Beyonce Shakira - Beautiful Liar','shakira, beyonce, music, video',1)
INSERT INTO Videos VALUES ( 2,'Beyonce Ego Remix','beyonce, music, video',1)
INSERT INTO Videos VALUES ( 3,'Beyonce Ego','beyonce, music, video',1)
在观看ID为1的视频时,我想要的是它应该根据标签显示相关视频,大多数匹配的术语应该排在最前面。
先谢谢
答案 0 :(得分:6)
您显示的模式,使用填充到Tags字符串中的每个视频的所有标记进行非规范化,都是为您的目的设计的 - 在TSQL中没有合理的方法来计算这种格式的两个字符串之间有意义的“共性”,因此没有合理的方法来检查哪些项目具有相对较高的共性,因此可能被视为“相关”。如果模式是不可触及的,那么你必须为此目的实现一个用户定义的函数(用C#或其他.NET语言),即使这样你也会或多或少地扫描整个表,因为没有合理的方法在这样的基础上索引。
如果您可以重新设计架构(还有两个表:一个用于存放标签,另一个用于表示标签和视频之间的多对多关系),可能会有更好的前景;在这种情况下,大概有多少(数量级)视频的预期,总体上有多少(同上)不同的标签,以及视频预期会有多少标签,这可能会让设计和有效方式得以实现追求你的目的。
编辑:根据评论,显然可以重新设计架构,但仍然没有给出关于我问的数字的指示,因此适当的指数和c将仍然是一个完全神秘的东西。无论如何,假设模式是这样的(每个表可以根据需要包含其他列,只需将它们添加到查询中;并且VARCHAR长度也无关紧要):
CREATE TABLE Videos (VideoID INT PRIMARY KEY,
VideoTitle VARCHAR(80));
CREATE TABLE Tags (TagID INT PRIMARY KEY,
TagText VARCHAR(20));
CREATE TABLE VideosTags (VideoID FOREIGN KEY REFERENCES Videos,
TagID FOREIGN KEY REFERENCES Tags,
PRIMARY KEY (VideoId, TagId));
即。只是经典的“多多关系”教科书的例子。
现在给出视频的标题,比如@MyTitle,可以很容易地查询与其最“相关”的5个视频的标题,例如:
WITH MyTags(TagId) AS
(
SELECT VT1.TagID
FROM Videos V1
JOIN VideosTags VT1 ON (V1.VideoID=VT1.VideoID)
WHERE V1.VideoTitle=@MyTitle
)
SELECT TOP(5) V2.VideoTitle, COUNT(*) AS CommonTags
FROM Videos V2
JOIN VideosTags VT2 ON (V2.VideoID=VT2.VideoID)
JOIN MyTags ON (VT2.TagId=MyTags.TagId)
GROUP BY V2.VideoId
ORDER BY CommonTags DESC;
答案 1 :(得分:0)
您最好分割模式,以便标签位于单独的表中,然后使用中间表链接到视频,这可能是...
select v.*
from Video v
inner join VideoTag vt
inner join Tag t on vt.TagID = t.TagID
on v.VideoID = vt.VideoID
where t.Description = @tagText
修改后的架构看起来像
视频
VideoID
Title
Description
标签
TagID
Description
VideoTag
VideoID
TagID
或者,您可以尝试使用更简单的查询,例如
select VideoID, Title, Description
from Video
where Tags like '%' + @tag + '%'
但这会匹配包含其他标签的标签(例如'art'和'martial art'),这就是为什么我认为将模式拆分为更好的解决方案。
答案 2 :(得分:0)
如果您使用的是代码,那么您只需要WHERE tag = 'thistag'
条件(如果同一个表中有一个代码),或者WHERE tag in (SELECT tag FROM tags_table WHERE video_id = this_video_id)
如果您将代码标准化为你的视频表,虽然任何一个解决方案可能会返回很多视频,所以你必须以某种方式修剪它。
这就是它变得有趣(而且很难)的地方;您不仅需要为每个视频存储一组标记,还需要为每个标记到视频关系存储一个关联分数。这会变得混乱和主观。
另一方面,如果你真的想要“最匹配的术语”(请在你的编辑中提到),我真正认为你需要的是数据挖掘查询。 Basket analysis是一种常用于显示“相关项目”的技术,当人们有兴趣查看其他对此项目感兴趣的人也感兴趣的内容时。这有点超出SQL查询,但如果你有SQL Server 2005,它是Analysis Services包的一部分。值得一看!
编辑:既然您已发布架构,我强烈建议您将Tags
字段规范化为另一个表格。围绕包含多个分隔项的字段进行编码非常困难,并由1st form normalisation解决。
答案 3 :(得分:0)
如果我已正确理解您的问题,因为您有一个视频表格,并且在该表格中有一列“标记”,其中一系列标记用逗号分隔;那么这里是LINQ查询...
dbDataContext db = new dbDataContext();
var movies =
from v in db.Videos
where v.Tags.Contains("Thriller")
select v;
我用VideoId,Name和Tags制作了一个快速表。我添加了一部电影'黑客帝国'并放置标签'惊悚片;动作片;戏剧片' - 该查询找到了黑客唱片。
作为旁注,有一个标签表,然后是一个包含VideoId的表格以及属于它们的标签,这不是更好吗?
只是一个想法。希望有所帮助。