我在HeidiSQL中运行的SQL代码一次又一次地运行,但是当我将它克隆到PHP并运行mysqli_query($ db,$ sql)时,它不起作用.
以下PHP/MySQL代码都是有效且完美的.
$sql = "select `ID`,`User` from (
select * from
(SELECT
`ID`,
`User`,
`BI`,
(@cnt:= @cnt + (`BI`/(select SUM(`BI`) from `ax`))) as `Entirety`
from `ax` as `t`
CROSS JOIN (SELECT @cnt := 0) AS var
order by `BI`
) d
where `Entirety`>(@rnd)
order by `BI`
) as `l`
cross join (select (@rnd := rand()) as `RandomValue`) as var2
limit 1;";
Run Code Online (Sandbox Code Playgroud)
然后我运行$ sql
$result = mysqli_query($db,$sql);
$results = mysqli_fetch_array($result);
Run Code Online (Sandbox Code Playgroud)
其中$ db是与MySQL服务器有效且开放的连接.但是当我这样做时,物体的回归
print_r($result);
Run Code Online (Sandbox Code Playgroud)
出来了
mysqli_result Object (
[current_field] => 0
[field_count] => 2
[lengths] =>
[num_rows] => 0
[type] => 0
)
Run Code Online (Sandbox Code Playgroud)
我不想要这个,而且num_rows应该是'1',因为这是HeidiSQL运行时显示的内容.这是HeidiSQL的图像显示结果:

有人有主意吗?
表的COLUMNS ax是ID,User和BI.在SQL中,它创建了两个名为"Entirety"的临时列,它是概率计数器和RandomValue一个名为rand()的列,从0到> 1.
此表中唯一的行的值为(1,1,10).虽然它是10,但它有一个Entirety'1',这意味着它是100%保证被选中.尽管如此,没有选择任何东西.
如果你在PHP中将EXPLAIN添加到你的查询中,mysqli会告诉你一个子查询的错误:
Impossible WHERE noticed after reading const tables
Run Code Online (Sandbox Code Playgroud)
和
const row not found
Run Code Online (Sandbox Code Playgroud)
这可能意味着很多,但在这种情况下,我的赌注是列中的无效值.我相当确定
select (@rnd := rand()) as `RandomValue`
Run Code Online (Sandbox Code Playgroud)
之后执行
where `Entirety`>(@rnd)
Run Code Online (Sandbox Code Playgroud)
因此没有设定.
那么,为什么它适用于您的客户?因为客户端保持连接.因此,它在第一次执行查询时失败,但第二次它在第一次执行时具有@rnd的存储值.您可以通过在@ rnd1中重命名@rnd来测试它并运行一次查询.
所以,解决方案是(正如Matt指出的那样)先设置变量@rnd然后再使用它.
以下是关于子查询中用户定义变量的相关SO问题:
来自我的客户:
第一次EXPLAIN:

第二次EXPLAIN:

希望这可以帮助.