PhP/MySQL:如何动态更改我的(大型且不断变化的)数据库

PhP/MySQL: how to dynamically change my (large and always changing) database

场景

我有一个包含 10.000 行的 MySQL 数据库。数据库设置:

ID   UniqueKey   Name     Url           Score   ItemValue
1    5Zvr3       Google   google.com    13      X
2    46cfG       Radio    radio.com     -20     X
3    2fg64       Yahoo    yahoo.com     5       X
.... etc etc etc

如您所见,每个项目都有一个分数。分数在不断变化。 Google现在可能是13分,明天可能是80分,或者-50分。

我想要的:

我想创建一个系统,根据项目的分数 在我当前的数据库中创建层次结构。现在我正在考虑 percentile ranks,这意味着得分最高的项目将接近 100%,而得分最低的项目将接近 0%。为此,我创建了一些代码来尝试实现此处显示的内容:http://www.psychstat.missouristate.edu/introbook/sbk14m.htm

这是我的代码:

$sql = "SELECT * FROM database order by Score";
$result = $conn->query($sql);
$count = 0;
while ($row = $result->fetch_assoc()) {
    $woow = $row['Score'];
    $sql = "SELECT * FROM database WHERE Score = $woow";
    $resultnew = $conn->query($sql);
    $somanythesame = $resultnew->num_rows;

    $itemPercentile = ( ($count/$result->num_rows + 0.5*$somanythesame/$result->num_rows) * 100 );

    $rowID = $row['ID'];
    $sql2 = "UPDATE database SET itemValue = $itemPercentile WHERE ID = $rowID";
    $conn->query($sql2);
    $count++;
}

这行得通,但有一个问题行不通:我的数据库中有很多项目,许多项目得分相同。为了说明我的问题,这里有一个非常简单的 10 行数据库,只有分数:

分数

-10
0
0
0
10
20
20
30
40
50

我的代码的问题是它没有为具有相同分数的项目给出相同的百分位数,因为它考虑了所有 计算的前几行,包括具有相同分数的行。

所以,对于带有Score of 0的第2、3、4项,应该是这样的:(1/10 + 0.5*1/10) * 100。问题是,对于第三项它将执行 (2/10 + 0.5*1/10) * 100 而对于第四项它将执行 (3/10 + 0.5*1/10) * 100.

那么,对于得分为 10 的第 5 项,应该(4/10 + 0.5*1/10) * 100。这进展顺利;仅对得分相同的项目不适用。


我不确定我是否解释得很好,我发现很难用正确的语言表达我的问题。如果您有任何疑问,请告诉我!感谢您的宝贵时间:)

您需要维护一个 "identical count" ($icount) 变量来跟踪具有相同分数的项目数和一个 "current score" ($score) 来跟踪当前得分。

$icount = 0;
$score = null;

$woow == $score 时增加 $icount 而不是 $count(相同值检查)。否则,将其添加到您的 $count 并递增,然后将 $icount 值重置为 0。

if ($woow == $score) {
    $icount++;
} else {
    $count += $icount + 1;
    $icount = 0;
}

最后,将您的 $score 值设置为最新的 $woow 以便在循环的下一次迭代中进行测试:

$score = $woow;

这将允许具有相同分数的项目具有相同的 $count 值,同时在找到新的 $score 时增加额外的 $icount 次。

您的最终代码将如下所示:

$sql = "SELECT * FROM database order by Score";
$result = $conn->query($sql);
$count = 0;
$icount = 0;
$score = null;
while ($row = $result->fetch_assoc()) {
    $woow = $row['Score'];
    $sql = "SELECT * FROM database WHERE Score = $woow";
    $resultnew = $conn->query($sql);
    $somanythesame = $resultnew->num_rows;

    $itemPercentile = ( ($count/$result->num_rows + 0.5*$somanythesame/$result->num_rows) * 100 );

    $rowID = $row['ID'];
    $sql2 = "UPDATE database SET itemValue = $itemPercentile WHERE ID = $rowID";
    $conn->query($sql2);
    if ($woow == $score) {
        $icount++;
    } else {
        $count += $icount + 1;
        $icount = 0;
    }
    $score = $woow;
}

您可以更改 $sql 查询:

 $sql = "SELECT *,count(*) FROM database group by Score order by Score";

在这种情况下,您获取带有计数的分数,而在 while 循环中不再需要 select。

甚至你可以 select MySQL 查询中的百分位数:

 Select t2.* , @fb as N , ((t2.fb1 + 0.5 * t2.fw)/@fb*100) as percentile from (
      Select t1.* , (@fb := @fb + t1.fw) as fb1 from (
           Select score,count(*) as fw From tablename group by score order by score ASC
           ) as t1
      ) as t2

我认为此查询 returns 您可能需要检查结果的大部分列。