0

「item_id」と「times_seen」の 2 つのフィールドを持つテーブルの最も単純な例にしましょう。

| item_id | times_seen |
----------+-------------
|   1001  |     48     |
|   1002  |     25     |
|   1003  |      1     |
|   1004  |     12     |
|   1005  |     96     |
|   1006  |     35     |

行をランダムに選択する方法を見つけようとしていますが、これまであまり選択されていない項目を優先します。

(明らかに、選択された後、2 番目のクエリが送信され、「表示回数」フィールドがインクリメントされます)

私の現在の「プロジェクト」はphp/mysqlのものですが、可能であれば言語にとらわれないソリューションが欲しいです。私はむしろ、他の場所に適応できる数学ベースのソリューションを望んでいます。私はphpソリューションに反対しているわけではありません。コードをコピーして貼り付けるだけでなく、コードがどのように機能するかを理解したいだけです。

4

2 に答える 2

2

SQLソリューションはどうですか?

select * from item order by times_seen + Rand()*100 limit 1;

ランダムに掛ける量(0から1の間の値)は、必要なランダム性の量によって異なります。

編集:http ://dev.mysql.com/doc/refman/5.0/en/mathematical-functions.html#function_rand

于 2012-04-05T22:43:09.670 に答える
2
  1. テーブル内のすべての行を取得します
  2. の最大値を決定するtimes_seen
  3. 各行に次の重みを割り当てますmax - times_seen
  4. 重みに基づいてリストから選択

ステップ 4 はトリッキーな部分ですが、次のようにすべて実行できます。

$max = 1;
$rows = array();

$result = mysql_query("SELECT * FROM table");
while ($row = mysql_fetch_array($result)){
    $max = max($max, $row['times_seen']);
    $rows[] = $row;
}

$pick_list = array();
foreach ($rows as $row){
    $count = $max - $row['times_seen'];
    for ($i=0; $i<$count; $i++) $pick_list[] = $row['item_id'];
}
shuffle($pick_list);
$item_id = array_pop($item_id);

すべてを SQL で行うには、次のようにします。

SELECT * 
FROM table 
ORDER BY RAND( ) * ( MAX( times_seen ) - times_seen ) DESC
LIMIT 1

これにより、重みが反比例する単一の行が選択されます。times_seen

于 2012-04-05T22:36:08.153 に答える