1

ランダムな勝者を決定するためにSQLクエリが必要です。各ユーザーには、独自の勝率があります。wining_oddsの値が高いほど、ユーザーは勝つ可能性が高くなります。テーブル構造を見てみましょう。

id    email            winning_odds
1     test@test.com    3
2     test2@test.com   5
3     test3@test.com   2
4     test4@test.com   1
5     test5@test.com   9

MySQLデータベース。テーブルには約100000行あります。勝者は一度だけです。メールはユニークです。誰かが解決策を持っていますか?

ありがとう。

4

4 に答える 4

1

Select email from user order by winning_odds*rand() limit 1

于 2012-11-07T20:21:44.027 に答える
1

私はこの質問がとても気に入りました。postgresql の回答を投稿しています。

select 
    *, generate_series(1, mytable.winning_odds) 
from 
    mytable 
order by 
    random() 
limit 1;

これがその仕組みです。テーブルの各行について、勝率としてその行を N 回複製します。

したがって、最初はクエリ結果を制限することなく取得できます。

  5 | test5@test.com |    9 | 9
  2 | test2@test.com |    5 | 3
  3 | test3@test.com |    2 | 1
  1 | test@test.com  |    3 | 1
  5 | test5@test.com |    9 | 5
  1 | test@test.com  |    3 | 3
  5 | test5@test.com |    9 | 2
  2 | test2@test.com |    5 | 4
  2 | test2@test.com |    5 | 5
  5 | test5@test.com |    9 | 1
  4 | test4@test.com |    1 | 1
  5 | test5@test.com |    9 | 7
  5 | test5@test.com |    9 | 4
  5 | test5@test.com |    9 | 6
  2 | test2@test.com |    5 | 1
  5 | test5@test.com |    9 | 8
  3 | test3@test.com |    2 | 2
  1 | test@test.com  |    3 | 2
  2 | test2@test.com |    5 | 2
  5 | test5@test.com |    9 | 3

これで、生成されたテーブルの任意の行をランダムに選択すると、winning_odds フィールドの確率が反映されます。

ランダムに並べて最初のレコードを取得するだけです。

 9 | test5@test.com |    9 | 2 

よろしく

于 2012-11-07T20:46:56.143 に答える
1

「オッズ」は整数ではなく、「9」を持つものは「1」よりも 9 倍可能性が高いと推測しています。

これを行う適切な方法は、累積合計を使用することです。次に、累積合計の最小値と最大値の間のランダムな値を生成し、その範囲内にあるレコードを選択します。次のクエリは、MySQL でこれを行います。

select t.*
from (select t.*,
             coalesce((select sum(odds) from t t2 where t2.id < t.id), 0) as cumsum,
             const.sumodds
      from t cross join
           (select rand()*sum(odds) as val from t) const
     ) t
where val between cumsum and cumsum + t.odds

ただし、これは非等価結合を行っているため、MySQL ではおそらく法外なコストがかかります。他のデータベースには、単一のクエリで累積合計を実行する機能があります。MySQL には、これを行う効率的な方法がありません。

クエリを最適化する方法は、問題の他の特定の要因によって異なります。「オッズ」はいくつの異なる値をとりますか? 一時テーブルを使用できますか?

今は解決策を書き出す時間がありませんが、もっと効率的な方法があります。Yアイデアは、問題を 2 つの検索に分割することです。最初のものは、どの「オッズ」値が勝つかを見つけます。2番目は、どの行が勝つかを見つけます。

詳細は次のとおりです。

(1) データをオッズで表にまとめます。このテーブルには 11 行あり、それぞれの「オッズ」と「カウント」が含まれます。

(2) 最初の行の 0 から始めて、各行の「count*odds」の合計を計算します。これは非常に少量のデータであり、すぐに実行されるため、上記のクエリをガイドとして使用できます。

(3) として乱数を計算しrand()*<sum of all odds>ます。次に、数値が cumsum と cumsum+odds の間にあるオッズを見つけます。

(4) 元のテーブルに戻り、次のようなクエリを発行します。

select *
from t
where odds = <winning odds>
order by rand()
limit 1
于 2012-11-07T20:58:26.113 に答える
0

私が質問を正しく理解している場合、あなたはテーブルからランダムなレコードを選択する方法を尋ねています。これは機能するはずです:

SELECT * 
FROM   tableName
ORDER BY RAND() LIMIT 0,1;

それでも、winning_odds値をどのように使用する予定であるかを明確にします。

于 2012-11-07T20:18:04.380 に答える