2

我有一个 MySQL SELECT 查询,它在同一个表中使用 20 个不同的比较。这是一个例子:

SELECT * FROM mytable
WHERE (col1 > (col2 * 0.25))
AND (col5 < col10) .......

SCORE我正在尝试根据返回的SELECT结果中调用的列的顺序来计算百分位等级。我尝试使用增量行号并COUNT(*)获取股票的排名和返回的结果总数,但不确定如何在某些结果相同的情况下分配相同的排名SCORE

这是我要计算的公式:

((COUNT(lower scores) + (COUNT(same/tied scores) / 2)) * 100) / COUNT(total results)

如何在同一结果行中找到较低分数、相同/并列分数和总分的数量,以便即时计算百分位数?

我试图避免使用存储过程,因为我希望我的应用程序管理员根据需要在我的应用程序管理区域中定制 SELECT 语句。

4

3 回答 3

3

使用上面的 Shlomi 的代码,这是我想出的用于计算百分位等级的代码(以防将来有人想计算这些):

SELECT 
    c.id, c.score, ROUND(((@rank - rank) / @rank) * 100, 2) AS percentile_rank
FROM
    (SELECT 
    *,
        @prev:=@curr,
        @curr:=a.score,
        @rank:=IF(@prev = @curr, @rank, @rank + 1) AS rank
    FROM
        (SELECT id, score FROM mytable) AS a,
        (SELECT @curr:= null, @prev:= null, @rank:= 0) AS b
ORDER BY score DESC) AS c;
于 2012-07-29T05:44:12.087 回答
2

这是一篇(我的)帖子,它解释了以下期间的排名SELECTSQL: Rank without Self Join

它使用用户定义的变量,即使在迭代行时也可以访问和分配这些变量。

使用相同的逻辑,它可以扩展到包括总分数、不同分数等。作为预览,这是一个典型的查询:

SELECT
  score_id, student_name, score,
  @prev := @curr,
  @curr := score,
  @rank := IF(@prev = @curr, @rank, @rank+1) AS rank
FROM
  score,
  (SELECT @curr := null, @prev := null, @rank := 0) sel1
ORDER BY score DESC
;
于 2012-07-18T14:37:37.627 回答
1

来自 Shlomi 和 Zishan(使用 Shlomi 的代码)的响应肯定不会给出准确的结果,正如我通过在我的一张大表上检查结果发现的那样。正如在其他地方回答的那样,显然不可能在单个 MySQL 查询中计算百分位等级: SQL rank percentile

使用用户定义变量的 Shlomi Noach 方法确实- 起初 - 看起来对于排名前几个百分比的排名很好,但对于表中排名较低的行,它很快就会退化。像我一样,亲自查看您的数据结果。

请参阅 Roland Bouman 的这篇博客文章,了解为什么 Shlomi在单个 SQL 语句中使用用户定义变量的方法不起作用,并提出了更好的解决方案:

http://rpbouman.blogspot.com/2009/09/mysql-another-ranking-trick.html

因此,我为此目的修改了 Bouman 的代码,这是我的解决方案,它必然结合了 PHP 和 MySQL:

步骤 1) 通过提交以下两个查询计算并存储每行的绝对排名:

SET @@group_concat_max_len := @@max_allowed_packet;

UPDATE mytable INNER JOIN (SELECT ID, FIND_IN_SET(
    score,
        (SELECT GROUP_CONCAT(
             DISTINCT score
             ORDER BY score  DESC
            )
        FROM mytable)
        ) AS rank
FROM mytable) AS a
ON mytable.ID=a.ID
SET mytable.rank = rank;

第 2 步:获取总行数(并将结果存储在 PHP 变量 $total 中)

SELECT COUNT(ID) FROM mytable

第 3 步:使用 PHP 循环遍历表以使用每行的绝对排名来计算行的百分排名:

3a)循环:

SELECT ID, rank FROM mytable

在 PHP 中将这些行值存储为 $ID 和 $rank

3b) 对于每一行运行:

$sql = 'UPDATE mytable INNER JOIN (
            SELECT (100*COUNT(ID)/'.$total.') percentile
            FROM mytable
            WHERE rank >= '.$rank.'
        ) a 
        ON mytable.ID = a.ID
        WHERE mytable.ID='.$ID.'
        SET mytable.percentile = a.percentile';

可能不是最有效的过程,但绝对准确,因为在我的情况下,'score' 值不会经常更新,所以我将上述脚本作为 cron 批处理操作运行,以保持百分位数排名最新。

于 2014-12-25T15:55:18.880 回答