Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

allw's avatar
Level 4

How to determine if multiple records' are more than a value then count?

I have a results table containing:

            $table->increments('id');
            $table->integer('mark')->nullable();
            $table->integer('paper_id')->unsigned();
            $table->string('student_id',14);

Students can have multiple results for a test (provided they are from different papers).

What I essentially need to do is, get any results where paper_id is one of test->paper->id where matching student ID (<|>|=) grade boundary but I do not want to have to do this for every student one by one.

Then I need to have a count of any students who were of a set grade.

Hope this makes sense?

Thanks!

Edit: Clarity

Looking to first Sum(any results with matching student_id, and that match any of an array of paper_id) then count(how many students were greater than a grade boundary)

something like (obviously this doesn't work correctly):

$count = Result::whereIn('paper_id', $paper_ids)->where('mark', '>', $grade_boundary)->count();
0 likes
8 replies
PatrickSJ's avatar

Just to make sure I understand. You want the count of the marks by student_id and paper_id? However, only count those marks that are greater than the grade boundary?

allw's avatar
Level 4

@PATRICKSJ - I knew I wouldn't be clear enough!

I am looking for the count of any student's results for a test which has a mark over the grade boundaries, but sometimes there are multiple papers so I would have to add the multiple papers then compare.

I could probably figure out a really ugly and slow version but ideally there is some way of doing this in a nice reasonably rapid way...

Hope this is clearer?

PatrickSJ's avatar

@ALLW - So, how many students have at least 1 mark greater than the boundary grouped by paper?

Edit: If I still have it wrong could you provide a table of how returned data should be organized?

allw's avatar
Level 4

@PATRICKSJ - no because the grade boundaries are for the sum of the results of both papers, not just one paper.

allw's avatar
Level 4
| 'Grade' | 'Number of students Who achieved Grade' |
|-------|---------------------------------------|
| 'U'     | 20                                    |
| '6'     | 300                                   |
| '7'     | 40                                    |
nolros's avatar

@patricksj assuming they are all in the results table you could do this

     $paperIds = [1,2,3];
        $min = 50;
        $max = 95;
        

    // $count will give you count & $results will be the collection 

        $count = count($results = DB::table('results')
            ->whereIn('paper_id', $paperIds)
            ->whereBetween('mark', [$min, $max])
            ->get());
allw's avatar
Level 4

@NOLROS - Yeah, but there can be multiple papers and that would give grades for per single paper so the boundaries would appear to be double what they should be with 2 papers triple with 3 etc

allw's avatar
allw
OP
Best Answer
Level 4

For anyone that is interested here is my not so elegant solution

    $boundaries = $this->getBoundaries($test_id);

    $count = [];

    $test = Test::where('id', $test_id)->with('papers')->first();
    $paper_ids = $test->papers->pluck('id');
    $results = Result::whereIn('paper_id', $paper_ids)->get();
    $student_ids = $results->pluck('student_id')->unique();
    $externals = External::where('test_id', $test_id)->get();

    
    $student_results = collect([]);
    for ($i = 0; $i < count($student_ids); $i++) {
      $temp = collect();
      $temp->put('mark', $results->where('student_id', $student_ids[$i])->sum('mark'));
      $student_results->push($temp);
    }

    for ($i = 0; $i < count($boundaries); $i++) {
      $temp_count = 0;

      if ($i === 0 && $i < count($boundaries)) {
        $temp_count = $student_results->where('mark', '<', $boundaries[$i + 1]->mark)->count();
      } elseif ($i === (count($boundaries)-1)) {
        $temp_count = $student_results->where('mark', '>=', $boundaries[$i]->mark)->count();
      } else {
        $temp_count = $student_results->where('mark', '>=', $boundaries[$i]->mark)->where('mark', '<', $boundaries[$i + 1]->mark)->count();
      }
      //return $externals->where('grade_id', $boundaries[$i]->grade_id)->pluck('count');
      $count[$i] = [
        'grade' => $boundaries[$i]->name,
        'count' => $temp_count,
        'external' => $externals->where('grade_id', $boundaries[$i]->grade_id)->pluck('numbers')->first(),
        ];
    }
    return $count;

Please or to participate in this conversation.