【问题标题】:Computing an average from different tables从不同的表计算平均值
【发布时间】:2013-07-10 20:11:09
【问题描述】:

对于一个很长的问题,我很抱歉,只是想详细解释一下。我的格式不是很好,也很抱歉。我有一个 PHP/MySQL 应用程序,它基本上不是真正的关系,因为我有一个用于所有学生分数的大表。除其他外,我能够计算每个科目的平均分数,这样平均分数就会出现在学生的分数旁边。现在我已经拆分了表格,有一些表格,我可以像以前一样成功地查询和创建学校成绩单。困难是我不能再计算任何科目的平均数了。

因为我有一张表,有 5 个科目,每个科目有 2 个测试,所以我查询数据并计算平均值如下:

一张表(列):

id date name exam_no term term year eng_mid eng_end mat_mid mat_end phy_mid phy_end bio_mid bio_end che_mid che_end

一个查询:

 $query = "SELECT * FROM pupils_records2 
 WHERE grade='$grade' && class='$class' && year =  '$year' && term ='$term'";
 $result = mysqli_query($dbc, $query);

if (mysqli_num_rows($result) > 0) {
$num_rows=mysqli_num_rows($result);
while($row = mysqli_fetch_array($result)){
//English
$eng_pupils1{$row['fname']} = $row['eng_mid'];
$eng_pupils2{$row['fname']} = $row['eng_end'];
$mid=(array_values($eng_pupils1));
$end=(array_values($eng_pupils2));

$add = function($a, $b) { return $a + $b;};

$eng_total = array_map($add, $mid, $end);

foreach ($eng_total as $key => $value){
 if ($value==''){
 unset ($eng_total[$key]);
 }
}

$eng_no=count($eng_total);

$eng_ave=array_sum($eng_total)/$eng_no;
$eng_ave=round($eng_ave,1);

//数学

$mat_pupils1{$row['fname']} = $row['mat_mid'];
$mat_pupils2{$row['fname']} = $row['mat_end'];
$mid=(array_values($mat_pupils1));
$end=(array_values($mat_pupils2));
$add = function($a, $b) { return $a + $b;};
$mat_total = array_map($add, $mid, $end);
foreach ($mat_total as $key => $value){
 if ($value==''){
 unset ($mat_total[$key]);
 }
}
print_r($mat_total);
$mat_no=count($mat_total);
echo '<br />';
print_r($mat_no);
$mat_ave=array_sum($mat_total)/$mat_no;
$mat_ave=round($mat_ave,1);
 }
}

//生物学 等等

我将表拆分为单独的表,并在单独的表中具有名称,计算平均值时不需要,所以我不会在这里展示。每个主题表都采用以下形式:

id date exam_no term year grade class test*

*测试将是 eng_mid 或 eng_end 或 mat_mid 等。

因为我只有一个查询返回 10 行(5 个科目,每个科目有两个测试:例如 eng_mid(英语MIT 考试)、eng_end(英语期末考试),我能够在一次调用中捕获所有行并打包将每个主题放入一个数组中,然后在 array_map 的帮助下计算出班级平均值。它可能不优雅,但效果很好。现在,我将每个测试都放在了自己的表中。

我试图编写一个关节以获得一个信号结果集,但查询失败。列如下:

我知道数据库设计并不是什么值得骄傲的事情,但是来自一个巨大的单表,这是一个巨大的进步(值得拍拍肩膀)。

我想做的是能够查询我所有的数据并计算班级平均值(每个班级大约 30 名学生)。我尝试使用单独的查询,但遇到了障碍,因为以前我会使用 WHILE 条件,如查询后所示,它可以拉出所有行并创建一个数组,我可以从中获得所需的结果。现在,由于连接不起作用,几个查询让我对如何归档相同的结果感到困惑。我还有一个单独的 $row 变量,这让我更加失衡!

是否有可能像我在臭名昭著的一张桌子上做的那样(从黑暗的一面)做平均,还是我的桌子设计如此混乱,我想要的只是人类无法实现的?

任何帮助将不胜感激。

【问题讨论】:

  • 拜托,在您编写任何更多 SQL 代码之前,您必须阅读 proper SQL escaping。您不能使用字符串插值或串联在查询中引入用户数据。 mysqlibind_param 方法为您执行此操作,使用该工具非常重要。
  • 这是示例代码,更接近我实际拥有的代码,它不准确,只是为了突出一个问题。也就是说,您的建议很有价值。
  • 确保永远不会这样的代码进入生产环境很重要,而且人们粘贴在这里的示例代码通常与他们在工作过程中所做的非常相似.我认为这样的代码一开始就不应该编写,即使你“只是在测试一些东西”,因为测试代码确实有一种意外提交和推出的方式,以及事故的代价这可能是惊人的。
  • @tadman 是的,如果这家伙的作业被黑了怎么办?这可能会导致惊人的事故,甚至美国国家安全局都会上当。
  • @tadman,请让其他人帮忙。每个人都来自某个地方。你一定很棒,没有写过糟糕的代码。

标签: php mysql sql database


【解决方案1】:

尝试使用union。会是这样的

select grade, test from math
union all
select grade, test from english
union all
....

另外,在我看来,更好的设计是使用类似 exams 的表格(警告,伪 DML):

id int primary key,
student_id int foreign key students
subject_id int foreign key subjects
exam_type_id int foreign key exam_types 
grade int(????)
  • exam_types table 只是中期和最终的,但如果需要,您将来可以轻松支持更多类型。
  • subjects table 将存储您拥有的各种科目(此时只有五个:math、eng、phy 等。

平均查询很简单(是的,您实际上可以在查询本身中执行aggregation

select student_id, avg(grade)
from exams
group by student_id

【讨论】:

  • 非常感谢@J0HN,让我试试看我得到了什么
  • 我还有一些路要走,我才能以这样的方式解决问题,让我自己拥有受试者,然后分别进行测试类型,这样测试的增加就会很好地扩展。感谢您为我指明正确的方向
猜你喜欢
  • 1970-01-01
  • 2021-08-09
  • 2021-10-15
  • 1970-01-01
  • 2020-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多