2011-01-26 3 views
1

ユーザーに2つのアイテムが提示され、2つのうちより良いものを選択するデータベースがあります。私は、ユーザーがまだ行っていない比較を表示したいだけです。私は私に比較するユーザーのための2つのランダムなアイテムを提供します(私の)SQLクエリを必要とする前に比較されていないSQLを使用して2つの行を選択する

項目テーブル

 
+--------+---------+ 
| itemId | name | 
+--------+---------+ 
| 1 | Dog  | 
| 2 | Cat  | 
| 3 | Fish | 
| 4 | Rat  | 
+--------+---------+ 

投票テーブル

 
+--------+--------------+--------------+--------+ 
| voteId | betterItemId | worseItemId | userId | 
+--------+--------------+--------------+--------+ 
| 1 |  1  |  2  | 1 | 
+--------+--------------+--------------+--------+ 
| 1 |  1  |  3  | 1 | 
+--------+--------------+--------------+--------+ 

:私は2つのテーブルを持っていますユーザは、互いに比較していない。

答えて

2
select a.itemId, a.name, b.itemId otherItemId, b.name othername 
from item a 
inner join item b on a.itemId < b.itemId 
where not exists (
    select * from vote v 
    where ((v.betterItemId = a.itemId and v.worseItemId = b.itemId) 
    or (v.betterItemId = b.itemId and v.worseItemId = a.itemId)) 
    and v.userId = 1234) # << enter the userId here 
order by rand() 
limit 1; 
  • まず、A-Bの組み合わせを生成するが、重複(例えば1-2と2-1)を防止するためにa.id<b.idを使用します。 ABの組み合わせごと
  • 次に、それをチェックする(任意の順列で、より良い、悪い、または悪化し、より良好な)アイテムが既にのuserId(クエリ内1234の一例)
  • 順序すべての結果によって投票されていないランダムorder by rand()
  • を使用して二つの別々の列として表示するために、両方のアイテムの選択、番組IDと名前でのみ1行
  • を取得する
  • 使用limit 1

、フロントエンドがこのために使用されるべきです。しかし、純粋にこれをMySQLで行うには、トリックが必要です。以下は書面の時点ではテストされていません。

select ItemId, name 
from 
(
    select a.itemId, a.name, @b := b.itemId 
    from item a 
    inner join item b on a.itemId < b.itemId 
    where not exists (
     select * from vote v 
     where ((v.betterItemId = a.itemId and v.worseItemId = b.itemId) 
     or (v.betterItemId = b.itemId and v.worseItemId = a.itemId)) 
     and v.userId = 1234) # << enter the userId here 
    order by rand() 
    limit 1 
) c 
union all 
select itemId, name 
from item d on d.itemId = @b 
+0

。可能であれば、実際には2つの行を使用できるという質問を各項目に1つずつ指定する必要がありました。これを統合する方法はありますか? – Moyersy

+0

これはフロントエンドから達成するのは簡単でしょうか?これは、MySQLを使用するのが難しいです – RichardTheKiwi

1

あなたは組み合わせがに投票されていないことを確認するためにnot exists句を使用することができます。これがうまく働いている

select a.itemId 
,  b.itemId 
from Items a 
join Items b 
on  a.ItemId < b.ItemId 
where not exists 
     (
     select * 
     from Vote 
     where userId = 42 
       and ((betterItemId = a.ItemId and worseItemId = b.ItemId) 
        or (worseItemId = a.ItemId and betterItemId = b.ItemId)) 
     ) 
order by 
     rand() 
limit 2 
+0

私はここで少し失われています - このビットの背後にあるロジックは何ですか "ジョイントアイテムb ON a.ItemId Moyersy

+0

@Moyersy:それは自己結合です、 'ON'条件は、' 1,2'と '2,1'の両方を選択するのを防ぎます。 – Andomar

関連する問題