【问题标题】:PhP/MySQL: how to dynamically change my (large and always changing) databasePhP/MySQL:如何动态更改我的(大型且不断变化的)数据库
【发布时间】:2017-06-26 16:48:42
【问题描述】:

场景

我有一个包含 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。

我想要什么:

我想创建一个系统,根据项目的分数,在我当前的数据库中创建层次结构。现在我在考虑百分比排名,这意味着得分最高的项目将接近 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。问题是,对于第 3 项,它将执行 (2/10 + 0.5*1/10) * 100,而对于第 4 项,它将执行 (3/10 + 0.5*1/10) * 100

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


我不确定我是否很好地解释了这一点,我发现很难用正确的语言表达我的问题。如果您有任何问题,请告诉我!谢谢你的时间:)

【问题讨论】:

    标签: php mysql database while-loop percentile


    【解决方案1】:

    您可以更改 $sql 查询:

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

    在这种情况下,您可以通过计数获取分数,而在 while 循环中不再需要选择。

    你甚至可以在 MySQL 查询中选择 Percentile:

     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
    

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

    【讨论】:

      【解决方案2】:

      您需要维护一个“相同计数”($icount) 变量来跟踪具有相同分数的项目的数量,以及一个“当前分数”($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;
      }
      

      【讨论】:

      • 更新以修复循环迭代中的分数持久性
      • 谢谢@StevenMoseley!抱歉回复晚了,但这个答案真的很好!它只是部分起作用。现在,score 0 的第一个项目具有 count = 2 值,score 0 的第 2、3 和 4 个项目具有 count = 3 值。你有什么机会可以帮助我吗?现在它对我来说有点太复杂了......提前谢谢!你是救生员
      猜你喜欢
      • 2016-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-02
      • 1970-01-01
      • 2020-06-09
      • 1970-01-01
      相关资源
      最近更新 更多