2

MySQLデータベースで、いくつかの数値属性から最も類似した行を見つけようとしています。この問題はこの質問に似ていますが、柔軟な数の比較と結合テーブルが含まれています。

データベース

データベースは2つのテーブルで構成されています。最初のテーブル、usersは、私が比較しようとしているものです。

id | self_ranking
----------------------------------
1       | 9
2       | 3
3       | 2

2番目の表は、ユーザーが特定のアイテムに付けた一連のスコアです。

id | user_id | item_id | score
----------------------------------
1  | 1       | 1       | 4
2  | 1       | 2       | 5
3  | 1       | 3       | 8
4  | 1       | 4       | 3

タスク

ランク付けされたすべてのアイテムを(自己スコアとともに)等しく評価して、特定のユーザーに「最も類似した」ユーザーを見つけたいと思います。したがって、完全に一致するのは、まったく同じ方法ですべての同じアイテムをランク付けし、自分自身を同じと評価したユーザーです。次に最適な選択は、1つのアイテムのランク付けがわずかに異なるユーザーです。

私は次の問題に直面しています:

  • 2つのテーブルを効率的に結合する
  • すべてのユーザーが同じアイテムをランク付けしているわけではないという事実に対処します。同一アイテムのランキングのみを比較したい。

誰かが私が合理的なクエリを構築するのを手伝ってもらえますか?私はMySQLにそれほど強いわけではないので、この答えが明白であるとしたら申し訳ありません。

出力

ユーザー4が自分自身を8にランク付けし、アイテム1=>4および2=>5の場合、ユーザー4の最も近いユーザーのクエリで1を返し、最も近いユーザーのuser_idを返します。

4

2 に答える 2

1

@eggyal の方法を少し改良して、照合できるアイテムの数を組み込みました。

SELECT   u2.user_id

-- join our user to their scores
FROM     (users u1 JOIN scores s1 USING (user_id))

-- and then join other users and their scores
    JOIN (users u2 JOIN scores s2 USING (user_id))
      ON s1.item_id  = s2.item_id
     AND u1.user_id != u2.user_id

-- filter for our user of interest
WHERE    u1.user_id = ?

-- group other users' scores together
GROUP BY u2.user_id

-- subtract the degree of difference in correlating scores from the number of correlating scores
ORDER BY (SUM(s1.item_id = s2.item_id) - 
  ( SUM(ABS(s2.score - s1.score) + ABS(u2.self - u1.self) ) ) ) DESC
于 2012-11-18T20:28:07.157 に答える
0
SELECT   u2.user_id

-- join our user to their scores
FROM     (users u1 JOIN scores s1 USING (user_id))

-- and then join other users and their scores
    JOIN (users u2 JOIN scores s2 USING (user_id))
      ON s1.item_id  = s2.item_id
     AND u1.user_id != u2.user_id

-- filter for our user of interest
WHERE    u1.user_id = ?

-- group other users' scores together
GROUP BY u2.user_id

-- and here's the magic: order in descending order of "distance" between
-- our selected user and all of the others: you may wish to weight
-- self_ranking differently to item scores, in which case just multiply
-- appropriately
ORDER BY SUM(ABS(s2.score - s1.score))
       + ABS(u2.self_ranking - u1.self_ranking) DESC
于 2012-11-18T19:34:58.977 に答える