使用SQL根据某些给定的条件进行计算

时间:2016-08-18 16:09:42

标签: php sql algorithm sorting

在我构建的一个检查应用程序中,我还没有想出一个方法来提出一个SQL语句来使这个任务成为可能。我们国家的评分系统只需要计算7个科目。在这些科目中,所有语言都是强制性的(在图片演示中标记为lang)。计算了2个最好的科学(标记为sci)。一个人类(标记为嗡嗡声)。第七主题可以是技术主题(标记技术),科学或人类,取决于哪个具有最佳标记。例如,给定表中的学生将具有来自MAT,ENG,KISW,PHY,CHEM,HIST和BST的标记。我使用数组编写PHP代码,它占用了太多的内存和时间,这让我担心它会让服务器停止运行。看看下面的代码,

function calculatePointsB($adm,$term,$class,$year,$exam){
global $db;

$points=array(
    "A"=>12,
    "A-"=>11,
    "B+"=>10,
    "B"=>9,
    "B-"=>8,
    "C+"=>7,
    "C"=>6,
    "C-"=>5,
    "D+"=>4,
    "D"=>3,
    "D-"=>2,
    "E"=>1
);
$choices=array();
$countable=array();
$monitor=array();
$grades=array();

$common_query_all=$db->prepare("SELECT marks,subject,sub_cat FROM averaged_marks WHERE adm_no=? AND sub_cat=? AND term=? AND class=? AND year=?");
$common_query_sp=$db->prepare("SELECT marks,subject,sub_cat FROM exmarks WHERE adm_no=? AND sub_cat=? AND term=? AND class=? AND year=? AND e_type=?");
//languages first
$langs=array();
if($exam=="All") {
    $getlang = $common_query_all;
    $getlang->execute(array($adm, "lang", $term, $class, $year));
}else{
    $getlang = $common_query_sp;
    $getlang->execute(array($adm, "lang", $term, $class, $year,$exam));
}
while($rst=$getlang->fetch(PDO::FETCH_ASSOC)){
    if($rst['marks']!=null) {
        $langs[$rst['subject']] = $rst['marks'];
        $grades[$rst['subject']]=$points[$rst['grade']];
        $countable[$rst['subject']] = $rst['marks'];
        array_push($monitor,$rst['sub_cat']);
    }else continue;
} unset($rst);

//sciences
$sciences=array();
if($exam=="All") {
    $getlang = $common_query_all;
    $getlang->execute(array($adm, "sci", $term, $class, $year));
}else{
    $getlang = $common_query_sp;
    $getlang->execute(array($adm, "sci", $term, $class, $year,$exam));
}
while($rst=$getlang->fetch(PDO::FETCH_ASSOC)){
    if($rst['marks']!=null) {
        $sciences[$rst['subject']] = $rst['marks'];
        array_push($monitor,$rst['sub_cat']);
    }else continue;
}unset($rst);
arsort($sciences);

//humanities
$humanities=array();
if($exam=="All") {
    $getlang = $common_query_all;
    $getlang->execute(array($adm, "hum", $term, $class, $year));
}else{
    $getlang = $common_query_sp;
    $getlang->execute(array($adm, "hum", $term, $class, $year,$exam));
}
while($rst=$getlang->fetch(PDO::FETCH_ASSOC)){
    if($rst['marks']!=null) {
        $humanities[$rst['subject']] = $rst['marks'];
        array_push($monitor,$rst['sub_cat']);
    }else continue;
}unset($rst);
arsort($humanities);

//technicals
$technic=array();
if($exam=="All") {
    $getlang = $common_query_all;
    $getlang->execute(array($adm, "tech", $term, $class, $year));
}else{
    $getlang = $common_query_sp;
    $getlang->execute(array($adm, "tech", $term, $class, $year,$exam));
}
while($rst=$getlang->fetch(PDO::FETCH_ASSOC)){
    if($rst['marks']!=null) {
        $technic[$rst['subject']] = $rst['marks'];
        $choices[$rst['subject']] = $rst['marks'];
    }else continue;
}unset($rst);
arsort($technic);

//add optional subjects to choices array
$iteration=0;
foreach($humanities as $sub => $value){
    $iteration++;
    if($iteration >1 && $iteration <= 3){
        $choices[$sub]=$value;
    }elseif($iteration==1){
        $countable[$sub]=$value;
        if($exam=="All") {
            $grades[$sub] = $points[getgradeinSub($adm, $sub, $term, $class, $year)];
        }else{
            $grades[$sub] = $points[getgradeinSpSub($adm, $sub, $term, $class, $year,$exam)];
        }
    }
}unset($humanities);

$iteration=0;
foreach($sciences as $sub => $value){
    $iteration++;
    if($iteration > 2 && $iteration <= 3){
        $choices[$sub]=$value;
    }elseif($iteration<=2){
        $countable[$sub]=$value;
        if($exam=="All") {
            $grades[$sub] = $points[getgradeinSub($adm, $sub, $term, $class, $year)];
        }else{
            $grades[$sub] = $points[getgradeinSpSub($adm, $sub, $term, $class, $year,$exam)];
        }
    }
}unset($sciences);
arsort($choices);

//get required and view the required number
//count number of keys
$count_compasory=array_count_values($monitor);
if($count_compasory['lang']==3 && $count_compasory['sci']>=2 && $count_compasory['hum']>=1){
    $remaining=7-count($countable);
    $iteration=0;
    foreach($choices as $sub => $value){
        $iteration++;
        if($iteration <= $remaining){
            $countable[$sub]=$value;
            if($exam=="All") {
                $grades[$sub] = $points[getgradeinSub($adm, $sub, $term, $class, $year)];
            }else{
                $grades[$sub] = $points[getgradeinSpSub($adm, $sub, $term, $class, $year,$exam)];
            }
        }
    }
    unset($choices);
    unset($countable);
    unset($monitor);
    unset($langs);
    unset($sciences);
    unset($humanities);
    unset($points);

    return array_sum($grades);
}
else unset($choices);
unset($countable);
unset($monitor);
unset($langs);
unset($sciences);
unset($humanities);
unset($grades);
unset($points);

return null;}

优秀的程序员会认为这是一种不好的做法。有没有办法为此编写SQL语句?获得问题的解决方案将是一个突破。桌子的图片如下。 Sample Table

2 个答案:

答案 0 :(得分:1)

我能在短时间内得到最好的,我采用与@GarethParker相同的方法,除了最后一个标记你还需要更多。

您可以在sqlfiddle

上试用
activity_main.xml

答案 1 :(得分:0)

如果没有测试数据来运行,并且不愿意创建自己的测试数据,我对制作可用的SQL犹豫不决,但听起来你想要的可能是UNION运算符。您可以将多个SQL查询的结果与其一起加入。因此,您可以拥有不同的条件,只需将它们结合起来。同样,下面的SQL只是一个例子,它可能不起作用,你可能需要自己调整它

SELECT * FROM exmarks WHERE sub_cat='lang'
UNION
SELECT * FROM exmarks WHERE sub_cat='sci' ORDER BY mark DESC LIMIT 2
UNION
SELECT * FROM exmarks WHERE sub_cat='hum' ORDER BY mark DESC LIMIT 1
UNION
SELECT * FROM exmarks WHERE sub_cat NOT IN ('lang', 'sci', 'hum') ORDER BY mark DESC LIMIT 1