2012-03-14 17 views
0

でユーザーを選択し、私は評価のテーブルを持っていると言う:、最も一般的な評価

create table ratings (
    user_id int unsigned not null, 
    post_id int unsigned not null, 
    rating set('like', 'dislike') not null, 
    primary key (user_id, post_id) 
); 

そしてid 1と、特定のユーザー、私は一般的でより多くの同類でユーザーを選択することができますか?そして、より多くのユーザーの嫌いな共通点ですか?そして、より多くの評価(好き嫌い)を共有しているユーザーは?私はクエリが非常に似ていると思う、私はまだそれらのうちのいずれかを把握することはできません買う。私は何らかの進歩について更新します。

すべてのヘルプは高く評価され、感謝!

答えて

1
select 
    r1.user_id as user1 
    ,r2.user_id as user2 
    ,r1.rating as rating 
    ,count(*) as num_matching_ratings 
from 
    ratings r1 
    inner join ratings r2 
     on r1.post_id = r2.post_id 
      and r1.rating = r2.rating 
      and r1.user_id <> r2.user_id --don't want to count 
             --matches with self 
where 
    r1.user_id = 1 -- change this to any user, or use a 
        -- variable to increase reusebility 
    and r1.rating = 'like' -- set this to dislike to common dislikes 
group by 
    r1.user_id 
    ,r2.user_id 
    ,r1.rating 
having 
    count(*) > 1 --show only those with more than 1 in common 
order by 
    count(*) desc 
/* limit 1 -- uncomment to show just the top match */ 

一緒にテーブルを結合することにより、我々はどこ秒occurancesの数をカウントすることができますユーザーは同様に記事を評価しました。この問合せは、最も一般的なものから最も一般的なものへの評価を返します。 「制限1」ステートメントのコメントを外すと、最も多くのものとの一致が返されます。

+0

私はあなたの質問の修正をusignしてしまいました。別の回答として投稿します。 – Sophivorus

+0

私は、クエリの唯一の欠陥は、順序がカウント(r2。user_id)、私はなぜ3列でグループ化する必要があるのか​​理解できません。私はr2.user_idによるグループ化で十分であると思います。 – Sophivorus

0

私の構文は、私は非常に頻繁に生のSQLを記述しないでください。このpsudocodeを考えることができます。

最初、私はその後、私は、カウント

で集計したいidが1

view1 = SELECT * FROM ratings, WHERE (user_id = 1)

ですテーブルが、私は評価

view2 = select * from view1, ratings, where(view1.rating = ratings.rating AND view1.post_id = records.post_id)

でそれに参加したい取得したいです

view3 = select count from view2 group by (user_id)

それから私はその最大値を得るでしょう。

これは、私の最初の考え方のアルゴリズム概要です。私はそれが特に効率的ではないと思うし、おそらくその構文を使用しないだろう。

+0

ありがとうございます、私はそれを試しています、それが動作するかどうかをお知らせします! – Sophivorus

+0

申し訳ありませんが、彼のコメントを削除した人は私のアルゴリズムの問​​題を指摘しました。私は以来訂正をしました –

1

は、この試してみて:

select r2.user_id from (
    select post_id, rating from ratings, 
    (select @userId := 2) init 
    where user_id = @userId 
) as r1 
join ratings r2 
on r1.post_id = r2.post_id and r1.rating = r2.rating 
where r2.user_id != @userId and r2.rating = 'like' 
group by r2.user_id 
order by count(*) desc 
limit 1 

それは、文字列を変更することによって、好き嫌いのために働く必要があります。ユーザーを変更するには、変数の割り当てを変更するだけです。以下は、両方嫌いのために働くと(ちょうどフィルタリング条件を削除することで)共通して好きなはずです

select r2.user_id from (
    select post_id, rating from ratings, 
    (select @userId := 2) init 
    where user_id = @userId 
) as r1 
join ratings r2 
on r1.post_id = r2.post_id and r1.rating = r2.rating 
where r2.user_id != @userId 
group by r2.user_id 
order by count(*) desc 
limit 1 
0

ChrisとMostachoの回答をもとに、私は次の質問をしました。私は毎回動作することを100%確信しているわけではありませんが、まだ欠陥が見つかりませんでした。

select r2.user_id 
from ratings r1 
join ratings r2 
on r1.user_id <> r2.user_id 
and r1.post_id = r2.post_id 
and r1.rating = r2.rating 
where r1.user_id = 1 
and r1.rating = 'like' 
group by r2.user_id 
order by count(r2.user_id) desc 
limit 1 

このクエリでは、より一般的な評価をユーザーにフェッチだけでwhere句からand r1.rating = 'like'を削除するには、ユーザ1と、より一般的な好みを持つユーザーのIDを返します。

関連する問題