расчет процентиля для огромной базы данных

У меня есть огромная база данных, содержащая информацию о студентах о тестовом коде и оценках, полученных за этот тестовый код. Мне нужно пересчитать процентные оценки для учащихся, соответствующие каждому тестовому коду. У меня есть код для серии тестового кода, но он не работает должным образом.

function recompute_percentiles()
{
if($_REQUEST[testcode]=="CAT B1" or $_REQUEST[testcode]=="CAT B2" or $_REQUEST[testcode]=="CAT B3" or $_REQUEST[testcode]=="CAT B4")
{

echo "<br />Got testcode: ".$_REQUEST[testcode];


$getsortedq=mysql_query("SELECT username, section1right as m from kmarks where testcode='.$_REQUEST[testcode].' order by section1right DESC");

if(!$getsortedq) 
echo "Could not get the sorted query";
else 
echo "got the sorted query quick";



$totalcount=mysql_num_rows($getsortedq);

while($r=mysql_fetch_array($getsortedq))
{
$u=$r[username];
$m=$r[m];
$array[$u]=$m;
}



$array2=$array;
//print_r($array2);

$updated=0;

foreach($array as $key=>$value)
{
$countsame=0;
foreach($array2 as $k=>$v)
{
    if($v>=$value) 
    $countsame++; 
    else
    break;
}
$countless = $totalcount - $countsame;

reset($array2);

$percentile=round($countless/$totalcount*100,2);

$updatep1q=mysql_query("UPDATE kmarks set percentile1=$percentile where   username='.$key.' and testcode='.$_REQUEST[testcode].'");

if(!$updatep1q)
  echo "<br />Could not update p1 for username: ".$key;
else
    $updated++;


}

echo "<br />Updated ".$updated." records in kmarks db, out of ".$totalcount." records for  testcode ".$_REQUEST[testcode];




}
}

person Shandhanu Mohan    schedule 30.09.2013    source источник
comment
Каковы предполагаемые результаты? В чем ошибка?   -  person Elias    schedule 30.09.2013
comment
получение 0 обновленных записей в kmmarks db, из 0 записей для тестового кода B1, в то время как я обновил несколько записей   -  person Shandhanu Mohan    schedule 30.09.2013
comment
Вы уверены, что вам нужны процентили, а не проценты?   -  person Dan Bracuk    schedule 30.09.2013


Ответы (2)


В этом коде есть несколько серьезных проблем, даже не касаясь функциональности...

1 синтаксис PHP

$_REQUEST[testcode]

Нехорошо, всегда используйте фигурные скобки!

$_REQUEST['testcode']

2 Склонность к инъекциям

Вы широко открыты для инъекций SQL и HTML/Javascript инъекция тоже

echo "<br />Got testcode: ".$_REQUEST[testcode]; //HTML injection...
//SQL injection
$getsortedq=mysql_query("SELECT username, section1right as m from kmarks where testcode='.$_REQUEST[testcode].' order by section1right DESC"); 

Всегда используйте надлежащую очистку (mysql(i)_real_escape_string($_REQUEST['testcode']) в зависимости от используемого mysql_ или mysqli). Или еще лучше: подготовленные операторы в случае с SQL...

3 Устаревание

Обязательное предупреждение mysql_*: функции mysql_ устарели, начиная с PHP 5.5. Не используйте их: используйте либо PDO, либо хотя бы функции mysqli_...

Функциональность

Это виновник:

$updatep1q=mysql_query("UPDATE kmarks set percentile1=$percentile where   username='.$key.' and testcode='.$_REQUEST[testcode].'");

Результирующий запрос будет выглядеть так:

UPDATE kmarks set percentile1=<somevalue>  --this is OK
where username='.<somevalue>.' and testcode='.$_REQUEST[testcode].'
                ^           ^                ^^^^^^^^^^^^^^^^^^^^^

Проблемы выделены... Есть нежелательные точки и целая плохая часть. Я полагаю, вы хотели что-то вроде этого

UPDATE kmarks set percentile1=<somevalue>  
where username='<somevalue>' and testcode='<somevalue>'

Вместо этого используйте его так (конечно, с санитизацией!!!):

//WARNING! STILL HAS SQL INJECTION --apply sanitization from #2 to make it safer...
$updatep1q=mysql_query("UPDATE kmarks set percentile1=$percentile where username='".$key."' and testcode='".$_REQUEST[testcode]."'");

Массивы нельзя использовать внутри строковых литералов, а операторы конкатенации . не требуются в случае простых переменных...

person ppeterka    schedule 30.09.2013
comment
внес изменения.. но теперь не получаю. Получил тестовый код: CAT B2 получил отсортированный запрос, в быстрых обновленных записях не упоминается.. - person Shandhanu Mohan; 30.09.2013

Кажется, что много кода. Вы можете сделать что-то вроде этого:

$results = $db->query("SELECT * FROM your_table ORDER BY sort_field");

$data = array();
while($row = $results->fetch_assoc()){
    $data[] = $row;
}

$chunks = array_chunk($data,ceil((count($data)/100)));
foreach($chunks as $key => $dataset){ 
$percentile = 99 - $key;

    foreach($dataset as $row){
        $db->query("UPDATE your_table SET percentile={$percentile} WHERE id={$row['id']}");
    }
}
person Community    schedule 01.01.2018