2016-07-06 40 views
1

テーブルから無作為に多数の記事を選択するクエリを作成しようとしていますが、記事に選択肢が加重される可能性があります。私は解決策を思いついたのですが、それは私にとって不器用なようです。誰かがそれをよりうまくやる方法について考えているのかどうか疑問に思っていました。私は少なくとも1つの記事が必要ですが、クエリが一度にいくつか返されれば役に立ちます。ここmysqlテーブルから重み付きランダム分布を選択する

は私のアプローチです:

テーブル -

mysql> describe randomiser; 
+---------+----------------------+------+-----+---------+----------------+ 
| Field | Type     | Null | Key | Default | Extra   | 
+---------+----------------------+------+-----+---------+----------------+ 
| id  | int(10) unsigned  | NO | PRI | NULL | auto_increment | 
| article | varchar(30)   | YES |  | NULL |    | 
| chance | smallint(5) unsigned | NO | MUL | 1  |    | 
| low  | int(10) unsigned  | NO | MUL | 0  |    | 
| high | int(10) unsigned  | NO |  | 0  |    | 
+---------+----------------------+------+-----+---------+----------------+ 

私の試験集団 -

mysql> select * from randomiser; 
+----+-------------+--------+-----+------+ 
| id | article  | chance | low | high | 
+----+-------------+--------+-----+------+ 
| 1 | common  | 128 | 1 | 128 | 
| 2 | uncommon |  64 | 129 | 192 | 
| 3 | infrequent1 |  32 | 193 | 224 | 
| 4 | infrequent2 |  32 | 225 | 256 | 
| 5 | infrequent3 |  32 | 257 | 288 | 
+----+-------------+--------+-----+------+ 

低い値と高い値は、挿入時に誰かが追加随時更新されますテーブルに新しい記事。

私の選択方法 -

SET @t:=(SELECT FLOOR(SUM(chance) * RAND() + 1) FROM randomiser); 
SELECT article FROM randomiser WHERE @t >= low AND @t <= high; 
  1. は、それは、単一の、効率的なステートメントに選択を組み合わせることが可能ですか?
  2. 1つだけでなく、いくつかのランダムな値を引き出す選択を書くことは可能ですか?

注 - 私は定義したとおり、テーブルには全く添付されていません。別の種類のレイアウトがあれば、より効率的になります。私は知りたいです!

答えて

1

複数のランダムな値を使用します

select t.article from 
(SELECT article, 
case when FLOOR(SUM(chance) * RAND() + 1) between low and high 
     then 1 else 0 end as chance 
FROM randomiser 
group by article) t 
where t.chance = 1 

以下のクエリを使用することができ、あなたはこのようにそれを行うことができます。

SELECT article 
FROM randomiser 
WHERE (SELECT FLOOR(SUM(chance) * RAND() + 1) FROM randomiser) BETWEEN low AND high; 

​​

またはINNER JOIN

SELECT article, `range` 
FROM randomiser 
INNER JOIN (
    SELECT 
     FLOOR(SUM(chance) * RAND() + 1) AS `range` 
    FROM randomiser 
) t 
WHERE `range` >= low AND `range` <= high; 

SQLFiddle Demo

+0

最初のものは動作していないようです。空のセットと2つの隣接する値を選択します。 2つ目はかなりうまくいくようです。 :) ありがとうございました !私はランダムな記事の任意の数をフェッチするためにそれを使用する唯一の方法は、制御プログラムからループで数回それを呼び出すことだろうと思いますか?またはいくつかのランダムな値を得ることができる何らかの方法を考えますか? –

+0

私はそれが複数のランダムな '範囲'の値で行われ、フェッチ後にそれらを区別するために異なる出力の名前を 'AS'を使って割り当てることができますが、それはまた不器用に思えます。私はこれについてもっと考えなければならないでしょう。 –

+0

私は、第2のアプローチの変形(内部結合を使用)と 'union'を使用して、複数のランダムな記事を返す問題の解決策を見つけることができました。それは最高ではないかもしれませんが、それはうまくいくようです。お手伝いありがとう ! –

1

あなたは上記のものは1つのクエリの

+0

これは動作するようには思えません。 'エラー1111(HY000):グループ関数の無効な使用 ' –

+0

@davidfurstクエリを変更しました –

+0

@davidfurst今すぐチェック –

関連する問題