我进行了一些搜索,但没有发现任何类似于我想要实现的内容。
基本上,我试图找出两个用户的投票习惯之间的相似性。
我有一个存储每个投票的表格,其中存储了:
voteID
itemID (the item the vote is attached to)
userID (the user who voted)
direction (whether the user voted the post up, or down)
我的目标是通过找出两件事来计算用户A和B之间的相似性:
(然后简单地将#2计算为#1的百分比,以达到粗略的相似性评级)。
我的问题是,如何找到两个用户的投票组之间的交集?(即如何充分计算第一点,而不会以非常低效的方式对每一个投票进行循环。)如果他们在不同的表中,INNER JOIN就足够了,我想......但是这显然不会在同一张桌子上工作(或者它会不会?)。
非常感谢任何想法。
答案 0 :(得分:5)
这样的事情:
SELECT COUNT(*)
FROM votes v1
INNER JOIN votes v2 ON (v1.item_id = v2.item_id)
WHERE v1.userID = 'userA'
AND v2.userUD = 'userB'
答案 1 :(得分:2)
这是一个让你更接近的例子:
SELECT COUNT(*)
FROM (
SELECT u1.userID
FROM vote u1, vote u2
WHERE u1.itemID = u2.itemID
AND u1.userID = user1
AND u2.userID = user2)
答案 2 :(得分:2)
假设将userID 1与userID 2进行比较
找出他们有多少票的共同点:
SELECT COUNT(*)
FROM Votes AS v1
INNER JOIN Votes AS v2 ON (v2.userID = 2
AND v2.itemID = v1.itemID)
WHERE v1.userID = 1;
寻找他们同样投票的时间:
SELECT COUNT(*)
FROM Votes AS v1
INNER JOIN Votes AS v2 ON (v2.userID = 2
AND v2.itemID = v1.itemID
AND v2.direction = v1.direction)
WHERE v1.userID = 1;
答案 3 :(得分:2)
自我加入是有序的。这就是你所问的所有问题:
SELECT v1.userID user1, v2.userID user2,
count(*) n_votes_in_common,
sum(case when v1.direction = v2.direction then 1 else 0 end) n_votes_same_direction,
(n_votes_same_direction * 100.0 / n_votes_in_common) crude_similarity_percent
FROM votes v1
INNER JOIN votes v2
ON v1.item_id = v2.item_id
答案 4 :(得分:2)
如果你想为一个用户做这件事(而不是一开始就知道两个用户),找到他们最匹配的人:
SELECT
v2.userID,
COUNT(*) AS matching_items,
SUM(CASE WHEN v2.direction = v1.direction THEN 1 ELSE 0 END) AS matching_votes
FROM
Votes v1
INNER JOIN Votes v2 ON
v2.userID <> v1.userID AND
v2.itemID = v1.itemID
WHERE
v1.userID = @userID
GROUP BY
v2.userID
然后你可以限制你认为合适(返回前10名,前20名,全部等)
我还没有对此进行测试,所以如果它没有按预期运行,请告诉我。
答案 5 :(得分:1)
你当然可以加入一张桌子。事实上,这就是你将要做的事情。将表连接到自身时必须使用别名。如果您的表没有PK或FK,则必须使用Union。 Union将删除重复项,而Union All则不会。