【问题标题】:Get Common Rows Within The Same Table获取同一个表中的公共行
【发布时间】:2009-02-04 20:15:50
【问题描述】:

我进行了一些搜索,但没有找到与我想要实现的目标完全一样的东西。

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

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

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. 他们以共同投票方式向同一方向投票的次数。

(然后简单地将 #2 计算为 #1 的百分比,以获得粗略的相似度评级)。

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

任何想法将不胜感激。

【问题讨论】:

    标签: sql mysql database relational self-join


    【解决方案1】:

    类似这样的:

    SELECT COUNT(*)
    FROM votes v1
    INNER JOIN votes v2 ON (v1.item_id = v2.item_id)
    WHERE v1.userID = 'userA'
    AND v2.userUD = 'userB'
    

    【讨论】:

      【解决方案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 名、全部等)

      我还没有对此进行测试,所以如果它没有按预期运行,请告诉我。

      【讨论】:

        【解决方案3】:

        这里有一个例子可以让你更接近:

        SELECT COUNT(*)
        FROM (
              SELECT u1.userID
              FROM vote u1, vote u2
              WHERE u1.itemID = u2.itemID
              AND u1.userID = user1
              AND u2.userID = user2)
        

        【讨论】:

        • 这可能是,欢迎您向我指出一些关于连接的文章,它解释了为什么一种方法比另一种更好。我没有大量的 SQL 经验。
        • 一切都与可读性和易于理解有关。看看这个答案:bit.ly/ansijoin
        【解决方案4】:

        假设用户 ID 1 与用户 ID 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;
        

        【讨论】:

          【解决方案5】:

          自联接是有序的。你问的都在这里:

          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
          

          【讨论】:

            【解决方案6】:

            您当然可以将表连接到自身。事实上,这就是你必须要做的。将表连接到自身时必须使用别名。如果您的表没有 PK 或 FK,则必须改用 Union。 Union 将删除重复项,Union All 不会。

            【讨论】:

            • 但是您如何使用不同的用户 ID 将其加入同一列?任何机会你都可以举个例子 - 因为我显然忽略了一些东西,在这里......
            • 我本来想去的,但是九边也打败了我。
            • 我的错,你的帖子出现在我输入我的一半的时候!
            猜你喜欢
            • 2014-07-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-10-10
            • 2021-07-21
            相关资源
            最近更新 更多