1

これは、ほとんどの「ランダムな順序」の質問とは反対です。データベースからランダムな順序でデータを選択したい。しかし、特定の選択を繰り返して、同じ順序を再度取得できるようにしたいと考えています。

現在の (ランダムな) 選択:

SELECT custId, rand() as random from
(
    SELECT DISTINCT custId FROM dummy
)

これを使用して、すべてのキー/行が乱数を取得します。これらの結果を昇順に並べると、ランダムな順序になります。

しかし、この選択を繰り返して、まったく同じ順序を取得したいと思います。私の考えは、乱数 (r) をセッションごとに 1 回 (たとえば "4") 計算し、この数を使用して何らかの方法でデータをシャッフルすることです。

私の最初のアイデア:

SELECT custId, custId * 4 as random from
(
    SELECT DISTINCT custId FROM dummy
)

(実際の "4" は 4005226664240702 のようになります)

これにより、行ごとに異なる数になりますが、実行ごとに同じ数になります。「r」を 5 に変更すると、すべての数値が変更されます。

問題は、ここでは乗算が十分でないことです。数を増やすだけですが、順序は同じに保たれます。したがって、他の種類の算術関数が必要です。

より抽象的な

私のデータ(AD)から始めます。kはキーで、rは現在使用されている乱数です。

    k    r
A = 1    4
B = 2    4
C = 3    4
D = 4    4

すべての行でkrを使用して計算を行うと、次のような結果が得られます。

    k    r
A = 1    4    --> 12
B = 2    4    --> 13
C = 3    4    --> 11
D = 4    4    --> 10

数字は何でもかまいませんが、昇順で並べ替えると、最初の順序とは異なる順序が必要になります。この場合、D、C、A、B、E.

r を 7 に設定すると、異なる順序 (C、A、B、D) になります。

    k    r
A = 1    7    --> 56
B = 2    7    --> 78
C = 3    7    --> 23
D = 4    7    --> 80

r = 7 を使用するたびに、同じ数字 => 同じ順序になるはずです。

k と r で計算を行う数学関数を探しています。RAND() 関数のシードは、サポートしている一部のデータベースではサポートされていないため、適切ではありません

r はすでにランダムに生成された数値であることに注意してください


バックグラウンド

1 つのテーブル - 2 つのデータ コンシューマー。1 つのコンシューマーはテーブルのランダムな 5% を取得し、もう 1 つのコンシューマーは他の 95% を取得します。データを取得するだけでなく、生成された SQL を取得します。そのため、同じデータを 2 回選択してはいけませんが、それでもランダムな 2 つの SQL があります。

4

3 に答える 3

1

You could try and implement the Multiply-With-Carry PseudoRandomNumberGenerator. The C version goes like this (source: Wikipedia):

m_w = <choose-initializer>;    /* must not be zero, nor 0x464fffff */
m_z = <choose-initializer>;    /* must not be zero, nor 0x9068ffff */

uint get_random()
{
    m_z = 36969 * (m_z & 65535) + (m_z >> 16);
    m_w = 18000 * (m_w & 65535) + (m_w >> 16);
    return (m_z << 16) + m_w;  /* 32-bit result */
}

In SQL, you could create a table Random, with two columns to contain w and z, and one ID column to identify each session. Perhaps your vendor supports variables and you need not bother with the table.

Nonetheless, even if we use a table, we immediately run into trouble cause ANSI SQL doesn't support unsigned INTs. In SQL Server I could switch to BIGINT, unsure if your vendor supports that.

CREATE TABLE Random (ID INT, [w] BIGINT, [z] BIGINT)

Initialize a new session, say number 3, by inserting 1 into z and the seed into w:

INSERT INTO Random (ID, w, z) VALUES (3, 8921, 1);

Then each time you wish to generate a new random number, do the computations:

UPDATE Random
SET
  z = (36969 * (z % 65536) + z / 65536) % 4294967296,
  w = (18000 * (w % 65536) + w / 65536) % 4294967296
WHERE ID = 3

(Note how I have replaced bitwise operands with div and mod operations and how, after computing, you need to mod 4294967296 to stay within the proper 32 bits unsigned int range.)

And select the new value:

SELECT(z * 65536 + w) % 4294967296
FROM Random
WHERE ID = 3

SQLFiddle demo

于 2013-10-24T18:19:47.583 に答える
1

これが SQL Server 以外に当てはまるかどうかはわかりませんが、通常、RAND()関数を使用する場合はシードを指定できます。同じシードを指定するたびに、ランダム化は同じになります。

したがって、シード番号を保存し、毎回それを使用して同じ乱数のセットを取得するだけでよいようです。

RAND に関する MSDN の記事

于 2013-10-24T14:11:19.400 に答える
0

各ベンダーは独自の方法でこれを解決しています。乱数の生成は難しいため、独自の実装を作成するのは困難です。

Oracle dbms_random はシードで初期化できます: http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_random.htm#i998255

SQL Server RAND() への最初の呼び出しでシードを提供できます: http://technet.microsoft.com/en-us/library/ms177610.aspx

MySql RAND() への最初の呼び出しでシードを提供できます: http://dev.mysql.com/doc/refman/4.1/en/mathematical-functions.html#function_rand

Postgresql は SET SEED または SELECT setseed() を使用します: http://www.postgresql.org/docs/8.3/static/sql-set.html

于 2013-10-24T14:18:53.807 に答える