我目前正在开发一个根据回答的问题匹配用户的应用程序。我在正常的 RoR 和 ActiveRecord 查询中实现了我的算法,但是使用它的速度很慢。将一位用户与 100 位其他用户匹配需要
Completed 200 OK in 17741ms (Views: 106.1ms | ActiveRecord: 1078.6ms)
在我的本地机器上。但仍然......我现在想在原始 SQL 中实现这一点,以获得更多的性能。但是我真的很难在 SQL 查询和诸如此类的东西加上计算等内容中了解 SQL 查询。我的头快要爆炸了,我什至不知道从哪里开始。
这是我的算法:
def match(user)
@a_score = (self.actual_score(user).to_f / self.possible_score(user).to_f) * 100
@b_score = (user.actual_score(self).to_f / user.possible_score(self).to_f) * 100
if self.common_questions(user) == []
0.to_f
else
match = Math.sqrt(@a_score * @b_score) - (100 / self.common_questions(user).count)
if match <= 0
0.to_f
else
match
end
end
end
def possible_score(user)
i = 0
self.user_questions.select("question_id, importance").find_each do |n|
if user.user_questions.select(:id).find_by_question_id(n.question_id)
i += Importance.find_by_id(n.importance).value
end
end
return i
end
def actual_score(user)
i = 0
self.user_questions.select("question_id, importance").includes(:accepted_answers).find_each do |n|
@user_answer = user.user_questions.select("answer_id").find_by_question_id(n.question_id)
unless @user_answer == nil
if n.accepted_answers.select(:answer_id).find_by_answer_id(@user_answer.answer_id)
i += Importance.find_by_id(n.importance).value
end
end
end
return i
end
所以基本上用户回答问题,选择他接受的答案以及这个问题对他有多重要。然后该算法检查 2 个用户的共同问题,如果用户 1 给出了用户 2 接受的答案,如果是,则添加用户 2 对每个问题给出的重要性,这构成了用户 1 的得分。对于 user2 也是相反的。除以可能的分数给出百分比,两个应用于几何平均值的百分比给出了两个用户的总匹配百分比。我知道相当复杂。告诉我是否解释得不够好。我只是希望我可以用原始 SQL 来表达这一点。性能就是这一切。
这是我的数据库表:
CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "username" varchar(255) DEFAULT '' NOT NULL); (left some unimportant stuff out, it's all there in the databse dump i uploaded)
CREATE TABLE "user_questions" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "user_id" integer, "question_id" integer, "answer_id" integer(255), "importance" integer, "explanation" text, "private" boolean DEFAULT 'f', "created_at" datetime);
CREATE TABLE "accepted_answers" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "user_question_id" integer, "answer_id" integer);
我猜 SQL 查询的顶部必须看起来像这样?
SELECT u1.id AS user1, u2.id AS user2, COALESCE(SQRT( (100.0*actual_score/possible_score) * (100.0*actual_score/possible_score) ), 0) AS match
FROM
但由于我不是 SQL 大师,只能做平常的事情,我的脑袋快要爆炸了。我希望有人能帮我解决这个问题。或者至少以某种方式提高我的表现!非常感谢!
编辑:
因此,根据向导的回答,我设法为“possible_score”获得了一个不错的 SQL 语句
SELECT SUM(value) AS sum_id
FROM user_questions AS uq1
INNER JOIN importances ON importances.id = uq1.importance
INNER JOIN user_questions uq2 ON uq1.question_id = uq2.question_id AND uq2.user_id = 101
WHERE uq1.user_id = 1
我试图用这个来获得“actual_score”,但它没有用。执行此操作时,我的数据库管理器崩溃了。
SELECT SUM(imp.value) AS sum_id
FROM user_questions AS uq1
INNER JOIN importances imp ON imp.id = uq1.importance
INNER JOIN user_questions uq2 ON uq2.question_id = uq1.question_id AND uq2.user_id = 101
INNER JOIN accepted_answers as ON as.user_question_id = uq1.id AND as.answer_id = uq2.answer_id
WHERE uq1.user_id = 1
编辑2
好吧,我是个白痴!我当然不能使用“as”作为别名。将其更改为 aa 并且有效!W00T!