2016-08-18 71 views
2

在我建,我還沒有想出一個辦法拿出一個SQL語句,以使此任務可以檢查應用程序之一進行計算。我國的評分制度只需要計算7個科目。在這些科目中,所有語言都是強制性的(圖示中標有lang)。計算出2門最好的科學(標記爲sci)。一個人類(標籤爲嗡嗡聲)。第七個主題可能是技術科目(標示爲科技),科學或人類取決於哪個科目具有最佳標記。例如,給定表中的學生將會記錄來自MAT,ENG,KISW,PHY,CHEM,HIST和BST的分數。我使用數組編寫了PHP代碼,它佔用了太多的內存和時間,這讓我擔心它會讓服務器停下來。看看下面的代碼,使用SQL基於某些給定的標準

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

+3

向我們提供一個sqlfiddle(http://sqlfiddle.com/)與(一個學生的)一些數據回答這個問題將極大地幫助。 對我來說這似乎應該可以通過一個選擇查詢來解決,同一張桌子上有幾個內部聯接 – Jester

+0

什麼是您的DBMS?應該是一個簡單的任務,如果它支持像'ROW_NUMBER' – dnoeth

+0

@Jester解析函數,這裏是SQL小提琴http://sqlfiddle.com/#!9/b80692 –

回答

1

我能想出在很短的時間我最好的,我採取了同樣的做法@GarethParker除了最後一個分數你需要更多。

,您可以嘗試在sqlfiddle

(SELECT * 
FROM averaged_marks 
WHERE sub_cat='lang' 
ORDER BY marks DESC)    #This select retrieves all 'lang' marks 
UNION 
(SELECT * 
FROM averaged_marks 
WHERE sub_cat='sci' 
ORDER BY marks DESC 
LIMIT 2)    #This select retrieves the highest 2 'sci' marks 
UNION 
(SELECT * 
FROM averaged_marks 
WHERE sub_cat='hum' 
ORDER BY marks DESC 
LIMIT 1)    #This select retrieves the highest 1 'hum' marks 
UNION 
(SELECT *   #This select retrieves the highest mark of the leftovers 
FROM averaged_marks 
WHERE averaged_marks.id NOT IN ( #This NOT IN contains the same select as above to get the first 6 marks and to make sure the 7th is not one of them. 
    SELECT temp.id 
    FROM 
     ((SELECT averaged_marks.id 
     FROM averaged_marks 
     WHERE sub_cat='lang' 
     ORDER BY marks DESC) 
     UNION 
     (SELECT averaged_marks.id 
     FROM averaged_marks 
     WHERE sub_cat='sci' 
     ORDER BY marks DESC 
     LIMIT 2) 
     UNION 
     (SELECT averaged_marks.id 
     FROM averaged_marks 
     WHERE sub_cat='hum' 
     ORDER BY marks DESC 
     LIMIT 1) 
     ) AS temp) 
ORDER BY marks DESC 
LIMIT 1) 
+0

它按我的預期工作。我真的很感動和感激你接受這一切的時間,特別是你獲得第七分的那一段。你完全破解了我正在尋找的東西。乾杯! –

+0

很高興我可以幫助:)如果你需要一些MySQL查詢幫助再次有時隨時標記我^^ – Jester

+0

再次感謝..我有一個問題。我的MySQL版本是否有bug?我使用的是MySQL 5.7,當我運行查詢時,它從另一個錄入號碼中抓取第七個主題並選擇一種語言(lang)。我的表格大約有5610條記錄。可能是什麼問題呢? –

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 
+0

這裏有一個SQL小提琴 - > http://sqlfiddle.com/#!9/b80692 –

+0

最後一個聯合是不正確的。它應該採取尚未採取的最高的一個。所以它可能來自'lang','sci','哼'。在他的例子中,情況並非如此。 – Jester