我的数据库中有两个与多对多关系连接的实体。我想知道列出哪些实体具有最相似性的最佳方法是什么?
我尝试使用intersect进行count(*),但查询花费的时间太长,无法在我的数据库中的每个条目上运行(大约有20k条记录)。运行我编写的查询时,CPU使用率跳至100%,数据库出现锁定问题。
以下是一些显示我尝试过的代码:
我的表格看起来像这样:
onload
(这有效,但速度非常慢) 这是我写的尝试列出它们的查询: 通常我也会过滤前1&添加where子句以获取一组特定的相关数据。
/* 20k records */
create table Movie(
Id INT PRIMARY KEY,
Title varchar(255)
);
/* 200-300 records */
create table Tags(
Id INT PRIMARY KEY,
Desc varchar(255)
);
/* 200,000-300,000 records */
create table TagMovies(
Movie_Id INT,
Tag_Id INT,
PRIMARY KEY (Movie_Id, Tag_Id),
FOREIGN KEY (Movie_Id) REFERENCES Movie(Id),
FOREIGN KEY (Tag_Id) REFERENCES Tags(Id),
);
说明: 电影有标签,用户可以尝试找到类似于他们根据其他具有相似标签的电影选择的电影。
答案 0 :(得分:4)
SELECT m.id, m.title, GROUP_CONCAT(DISTINCT t.Descr SEPARATOR ', ') as tags, count(*) as matches
FROM stack.Movie m
LEFT JOIN stack.TagMovies tm ON m.Id = tm.Movie_Id
LEFT JOIN stack.Tags t ON tm.Tag_Id = t.Id
WHERE m.id != 1
AND tm.Tag_Id IN (SELECT Tag_Id FROM stack.TagMovies tm WHERE tm.Movie_Id = 1)
GROUP BY m.id
ORDER BY matches DESC
LIMIT 15;
编辑: 我刚刚意识到它适用于M $ SQL ......但也许可以做类似的事情......
答案 1 :(得分:1)
你应该决定一个命名约定并坚持下去。表是单数还是复数名词?我不想进入那场辩论,而是选择其中一种。
无法访问您的数据库,我不知道这将如何执行。这只是我的头脑。您还可以通过M.id
值来限制它,以找到单个电影的最佳匹配,我认为这会提高性能。
此外,TOP x
可让您获得x最接近的匹配。
SELECT
M.id,
M.title,
SM.id AS similar_movie_id,
SM.title AS similar_movie_title,
COUNT(*) AS matched_tags
FROM
Movie M
INNER JOIN TagsMovie TM1 ON TM1.movie_id = M.movie_id
INNER JOIN TagsMovie TM2 ON
TM2.tag_id = TM1.tag_id AND
TM2.movie_id <> TM1.movie_id
INNER JOIN Movie SM ON SM.movie_id = TM2.movie_id
GROUP BY
M.id,
M.title,
SM.id AS similar_movie_id,
SM.title AS similar_movie_title
ORDER BY
COUNT(*) DESC