2

それで、私が遭遇した興味深い問題。簡単な解決策があると確信していますが、それが何であるかはわかりません。:)

基本的に、次のような非常に単純なデータベースを想像してください。

----------------
T1
----------------
  r  |  nID
---------------
  1  |   A
  2  |   B
----------------




----------------
T2
----------------
 nID |  val
---------------
  A  |   XXX
  B  |   L
  B  |   M
  B  |   N
  B  |   P
----------------

基本的に、表 2 は表 1 を参照します。ここで、A または B からランダムな行を選択したいと思います。ただし、最初に A と B をランダム化し、次に関連する値を選択したいと思います。

つまり、コインを投げXXXます。尾、L, M, N,またはP

私の現在のクエリは、2 つのテーブル、 orders by RAND()、 then を結合しますLIMIT 1。ただし、これにより、B 値が選択される確率が、A 値が選択される確率よりもはるかに高くなります。私はPHPを使用しているので、2つのクエリを実行するだけで簡単に実行できますが、1つのクエリを実行する方がはるかに整理されるので、皆さんの推奨事項を確認したいと思います.

解決策はありますか?=)

編集:

これが私の現在のクエリですが、機能していません。理由がわからない!

SELECT *
FROM t2
WHERE
    nID =
    (
        SELECT nID
        FROM t1
        ORDER BY RAND()
        LIMIT 1
    )
ORDER BY RAND()
LIMIT 1

編集2:

私が抱えている問題を実証するために、テスト ケースを作成しました。まず、次のテーブルを作成しました。

T1とT2

を選択する確率を、 、、、またはを選択する確率XXXと同じにしたい。私が持っているクエリはそれを行うべきですよね?だから私はそれをテストしました。次のスクリプトは、クエリを 5000 回実行し、結果をカウントします。それらは約 50 ~ 50 で、約 2500 回表示され、他のすべてのものも約 2500 回表示されます。LMNPXXX

$a = 0;
$b = 0;
$i = 0;
while ($i < 5000)
{
    $query = mysql_query("
        SELECT *
        FROM t2
        WHERE
            nID =
            (
                SELECT nID
                FROM t1
                ORDER BY RAND()
                LIMIT 1
            )
        ORDER BY RAND()
        LIMIT 1
        ") or die(mysql_error());

    $result = mysql_fetch_array($query);
    if ($result['val'] == 'XXX')
    {
        $a++;
    }
    else
    {
        $b++;
    }

    $i++;
}

echo "XXX - $a<br />";
echo "Other - $b<br />";

結果は次のとおりです。

XXX - 937
Other - 4063

もう一度実行してみましょう。

XXX - 968
Other - 4032

そして、もう一度実行してみましょう。

XXX - 932
Other - 4068

これは、私のクエリで予想される 50 対 50 の分割ではありません。一体何が起こっているのですか?助けてくれてありがとう、みんな!

4

4 に答える 4

2

質問のサブクエリは、外側のクエリごとに 1 回実行されると予想されますが、そうではないようです。以下は、あなたが求めているものをあなたに与えるかもしれないと思います:

SET @randID = (SELECT nID
FROM T1
ORDER BY RAND()
LIMIT 1);

SELECT VAL
FROM T2
WHERE nID = @randID
ORDER BY RAND()
LIMIT 1;

(SQL フィドル)

于 2012-05-20T17:32:04.203 に答える
2

内部クエリの例は複数回評価されます。 A または B onceJOINを選択する場合は、 a ;などのように書き直す必要があります。

SELECT q2.nID, q2.val
FROM ( SELECT nID FROM T1 ORDER BY RAND() LIMIT 1 ) q1
JOIN T2 q2 ON q1.nID = q2.nID
ORDER BY RAND()
LIMIT 1

小さなテーブルで作業している場合、このクエリは問題ありませんが、たとえばORDER BY RAND()大きなテーブルに使用しない理由については、こちらをお読みください。

ここでデモ。

于 2012-05-20T18:17:37.887 に答える
1

以下のクエリを試してください

SELECT `table2`.*  FROM `table2` WHERE table2.field1 = (Select table1.field2 from table1 order by RAND() limit 0,1) LIMIT 0,1

ここでは、両方のテーブルの列名 field1 と field2 を想定しているため、テーブル構造に応じてフィールド名を使用してください。

ありがとう

于 2012-05-19T05:52:11.357 に答える
0
SELECT
    CASE rq.r WHEN '1' THEN t1q.r ELSE t2q.nID END AS Col1,
    CASE rq.r WHEN '1' THEN t1q.nID ELSE t2q.val END AS Col2
FROM
    (SELECT CASE WHEN RAND() < 0.5 THEN '1' ELSE '2' END AS r) AS rq
    JOIN (SELECT * FROM T1 ORDER BY RAND() LIMIT 1) as t1q
    JOIN (SELECT * FROM T2 ORDER BY RAND() LIMIT 1) as t2q

観察: このクエリは、1 つしか使用されていない場合でも、両方のテーブルからランダムな行を選択する必要があるため、非効率的です。おそらく、より良い方法が存在します。

于 2012-05-19T06:10:52.940 に答える