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.

我当前的查询连接了两个表,orders by RAND(),然后是LIMIT 1。但是,这使得选择 B 值的可能性比选择 A 值的可能性大得多。我正在使用 PHP,所以我可以轻松地运行两个查询,但是运行一个查询会更整洁,所以我想看看你们推荐什么。

有什么解决办法吗?=)

编辑:

这是我当前的查询,但它不起作用。不知道为什么!

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

您会期望问题中的子查询将在每个外部查询中运行一次,但看起来情况并非如此。我认为以下内容可能会给您您所追求的:

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一次,您需要重写它,例如作为 a JOIN;

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

观察:此查询效率低下,因为它需要从两个表中选择一个随机行,即使只使用了一个。也许存在更好的方法。

于 2012-05-19T06:10:52.940 回答