我不确定我想要做的事情是否纯粹在SQL中可行,但让我们试试。
让我们假设3个表:
在亲和力表中,我会为每个用户/主题存储从-2(讨厌这个主题)到+2(喜欢这个主题)的亲和力。做一个ABS(affinity_u1 - affinity_u2)会给我一个主题,在2个用户之间,得分在0(完全亲和力)到4(大差异)之间。
我的问题是,在SQL中,我如何计算所有其他用户对所有实践的兴趣有多相似,以便我可以将它们从与我几乎相同的兴趣排列到没有共同兴趣。
示例输入,3个用户,3个主题,不同的亲和力:
INSERT INTO affinity (user, topic, affinity) VALUES
(1, 1, 2),
(2, 1, 2),
(3, 1, -1),
(1, 2, 2),
(2, 2, 1),
(3, 2, 0),
(1, 3, 1),
(2, 3, 2),
(3, 3, -2);
假设我是用户1,作为输出我期望:
SELECT other_user, overall_average_affinity_compared_to_me FROM...
Row1: 2, 0.66
Row2: 3, 2.66
(与我最接近的其他用户是2,平均亲和力增量为0.66,然后是用户3,平均亲和力增量为2.66)。
(我并不真正关心价值本身,只是排名)
如果我的问题不是很清楚,请告诉我
答案 0 :(得分:1)
SELECT u2.username, AVG(ABS(a1.affinity - a2.affinity)) similarity
FROM `user` u1
JOIN affinity a1
ON a1.user = u1.id
JOIN affinity a2
ON a2.topic = a1.topic
AND a2.user != a1.user
JOIN `user` u2
ON u2.id = a2.user
WHERE u1.id = :user_id
GROUP BY u2.username
ORDER BY similarity
没有用户名:
SELECT a2.user, AVG(ABS(a1.affinity - a2.affinity)) similarity
FROM affinity a1
JOIN affinity a2
ON a2.topic = a1.topic
AND a2.user != a1.user
WHERE a1.user = :user_id
GROUP BY a2.user
ORDER BY similarity
值得注意的是,在用户对不同数量的主题进行排名的情况下,这不是比较相似性的好方法。