4

私の目的

一意のみを含む複数のランダム行を取得しようとしていますuseridが、type列がランダムになるようにするには、またはtypeのみを使用できます。問題のテーブルには、常に 1,000 行未満が含まれます。01

私のテーブル

CREATE TABLE tbl_message_queue (
  userid bigint(20) NOT NULL,
  messageid varchar(20) NOT NULL,
  `type` int(1) NOT NULL,
  PRIMARY KEY (userid,messageid,`type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

サンプルデータ

userid  |   messageid   |   type
---------------------------------------------------
4353453 |   518423942   |   0
4353453 |   518423942   |   1
2342934 |   748475435   |   0
2342934 |   748475435   |   1
7657529 |   821516543   |   0
7657529 |   821516543   |   1
0823546 |   932843285   |   0
0823546 |   932843285   |   1

何を除外するか

ORDER BY RAND()これらのタイプのクエリのうち少なくとも 18,000 を超えるクエリが常にアプリケーションによって実行され、高負荷を引き起こしているため、使用することは現実的ではありません。SELECT DISTINCTorを使用するGROUP BYと (明らかに) より効率的で、常に一意のuseridものを選択しますが、常に許容可能な負荷とtype等しくなります。0

一般的な方法は列を作成することですが、別の方法のみidを探しています。グループの主キーは必須であり、アプリケーションに深く統合されているため変更できませんが、各列の構造は変更できます。

ありがとう。

4

1 に答える 1

2

あなたの質問についての私の理解は、それぞれuserid2つのエントリがありますが、ランダムに1つだけ抽出したいということです。

これを実現するには、それぞれの unique に対して 0 から 1 の間のランダムな値を生成し、useridこのリストを開始リストと結合する必要があります。

SELECT a.* FROM tbl_message_queue AS a
    JOIN ( SELECT userid, FLOOR(2*RAND()) AS type 
           FROM tbl_message_queue GROUP BY userid ) AS b
    ON ( a.userid = b.userid AND a.type = b.type );

しかし、ORDER BY RAND()うまくいかない場合は、妥協する必要があるかもしれません。

上記のシーケンスでは、任意の 2 つのユーザー ID に相関関係はありません。つまり、ユーザー A がタイプ 0 を取得するという事実は、ユーザー B が何を持っているかについては何もわかりません。

ユース ケースに応じて、2 つのクエリを使用してランダム性の低い (ただし「明らかにランダムな」) シーケンスを取得できます。

SELECT @X := FLOOR(2*RAND()), @Y := POW(2,FLOOR(2+14*RAND()))-1;

SELECT * FROM tbl_message_queue WHERE (((userid % @Y) & 1) XOR type XOR @X);

このようにして、ランダムな抽出と思われるものを取得できます。実際に起こることは、ユーザー ID が相関しているということであり、数十の異なる抽出しか可能ではありません。しかし、単純な演算子のみを使用し、JOIN を使用しないため、このクエリは非常に高速です。

于 2012-10-01T00:23:40.823 に答える