所以,我遇到了一些有趣的问题。我确信这是一个简单的解决方案,但我不确定它是什么。 :)
基本上,想象一个非常简单的数据库,如下所示:
----------------
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
。
我当前的查询加入了两个表,按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
为了演示我遇到的问题,我创建了一个测试用例。首先,我创建了以下表格:
我希望选择XXX
与选择L
,M
,N
或P
相同的几率。我的查询应该这样做,对吧?所以我测试了它。以下脚本运行查询5000次,并计算结果。它们应该是大约50-50,XXX
出现大约2500次,其他一切也出现大约2500次。
$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分割。究竟是怎么回事?谢谢你的帮助,伙计们!
答案 0 :(得分:2)
你会期望你的问题中的子查询将在每个外部查询中运行一次,但看起来并非如此。我认为以下内容可能会为您提供所需的内容:
SET @randID = (SELECT nID
FROM T1
ORDER BY RAND()
LIMIT 1);
SELECT VAL
FROM T2
WHERE nID = @randID
ORDER BY RAND()
LIMIT 1;
答案 1 :(得分:2)
您的示例内部查询会被多次评估,如果您希望它选择A或B 一次,则需要重写它,例如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
如果您正在处理小型表,则此查询应该没问题,但请阅读here for example,了解为何不应将ORDER BY RAND()
用于大型表。
演示here。
答案 2 :(得分:1)
请尝试下面的查询
SELECT `table2`.* FROM `table2` WHERE table2.field1 = (Select table1.field2 from table1 order by RAND() limit 0,1) LIMIT 0,1
这里我假设两个表的列名字段field1和field2,所以请根据您的表格结构使用字段名称。
感谢
答案 3 :(得分: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
观察:此查询效率低下,因为它需要从两个表中选择一个随机行,即使只使用了一个。也许存在更好的方式。