为什么这个 php 查询不起作用?

Why this php query does not work?

所以我正在为我的统一游戏制作高分系统,使用mysql、php。

为了获取存储在数据库中的高分信息,我这样写,(数据库有 'score'、'name' 列,但没有 'rank' 列名称)

$sql = "SELECT id, score, name, CASE\n"
        . " WHEN @prev_value = score THEN @rank_count\n"
        . " WHEN @prev_value := score THEN @rank_count := @rank_count + 1\n"
        . "END AS rank\n"
        . "FROM BBR\n"
        . "ORDER BY score DESC LIMIT $min, $max";

$result = mysql_query($sql) or Die('Query failed: ' . mysql_error());

$info = "";
while($found = mysql_fetch_array($result)){
    $info = $info .'@'. $found['name'] .':'. $found['score'] .':'. $found['rank'];
}
echo $info;

并且在统一中,我收到此信息并拆分为每个字符串。

string[] score = serverHighScores[x].Split(':');

但是这个在score[0](名字)、score[1](分数)上工作得很好,但是在score[2](排名)上不起作用。

为什么?我该如何解决? 谢谢


这个查询是

SET @prev_value = NULL;
SET @rank_count = 0;
SELECT id, score, name, CASE
    WHEN @prev_value = score THEN @rank_count
    WHEN @prev_value := score THEN @rank_count := @rank_count + 1
END AS rank
FROM BBR
ORDER BY score DESC

这在 phpmyadmin SQL.

中运行良好

我会这样写查询:

SELECT b.id
     , b.name
     , @rank_cnt := IF(@prev_score = b.score,@rank_cnt,@rank_cnt+1) AS rank
     , @prev_score := b.score AS score
  FROM BBR b
 CROSS
  JOIN ( SELECT @rank_cnt := 0, @prev_score := NULL) i
 ORDER BY b.score DESC, b.id DESC

注意:我们通过此查询观察到的行为得到保证。 MySQL 参考手册特别警告不要以这种方式使用用户定义的变量。但是我们观察到的行为(至少对于 MySQL 5.1 和 5.5)是一致的。

在比较之后完成 @prev_score 的赋值很重要,这就是为什么列在 SELECT 列表中按原样排序的原因。

我认为 CASE 表达式中的赋值(它在问题查询中的方式)"work" 与我们期望的方式不同。我认为这与 MySQL 执行的操作顺序有关。我总是将表达式的结果分配给 SELECT 列表中的用户定义变量,如上所示。

表达式 IF(@prev_score = b.score,@rank_cnt,@rank_cnt+1) 可以替换为等效的 CASE 表达式:

  CASE WHEN @prev_score = b.score THEN @rank_cnt ELSE @rank_cnt+1 END

请注意,表达式 return 正在计算一个值,而不是尝试进行赋值。

我更喜欢在语句中初始化用户定义的变量,而不是依赖于单独的 SET 语句。在这种情况下,我们并不真正关心内联视图 i 编辑的内容 return,除了我们希望它正好 return 一行(因为 JOIN 操作)。 .. 我们真的更感兴趣的是内联视图查询在外部查询运行之前具体化,以便在外部查询运行时初始化变量。

此外,我在 ORDER BY 中添加了另一个表达式,使结果更具确定性。

...(将 link 添加到 MySQL 参考手册中有关用户定义变量警告的适用部分)


mysql_ 接口函数已弃用。请改用 mysqliPDO 界面。