在同一个表中获取公共行

时间:2009-02-04 20:15:50

标签: sql mysql database relational self-join

我进行了一些搜索,但没有发现任何类似于我想要实现的内容。

基本上,我试图找出两个用户的投票习惯之间的相似性。

我有一个存储每个投票的表格,其中存储了:

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之间的相似性:

  1. 他们共同投票的数量。也就是说,他们在同一个帖子上投票的次数(此时方向无关紧要)。
  2. 他们以相同的方向投票的次数,共同投票
  3. (然后简单地将#2计算为#1的百分比,以达到粗略的相似性评级)。

    我的问题是,如何找到两个用户的投票组之间的交集?(即如何充分计算第一点,而不会以非常低效的方式对每一个投票进行循环。)如果他们在不同的表中,INNER JOIN就足够了,我想......但是这显然不会在同一张桌子上工作(或者它会不会?)。

    非常感谢任何想法。

6 个答案:

答案 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则不会。