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

Rretzko's avatar
Level 15

Left Join results in fewer rows

Hi folks - My understanding of left joins is that if a row exists on the second table, it is added to the results set and if a row doesn't exist on the second table, the rows from the first table are still returned. The sql below returns 95 records. When I introduce the left-join on the phone_numbers table, the result set drops to 80. Maybe I'm misunderstanding the left-join or simply using it incorrectly. Your eyes and experience are appreciated!

95 rows:

DB::table('candidates')
            ->join('audition_results', 'candidates.id', '=', 'audition_results.candidate_id')
            ->join('students', 'candidates.student_id', '=', 'students.id')
            ->join('users', 'students.user_id', '=', 'users.id')
            ->where('candidates.version_id', $this->versionId)
            ->where('candidates.status', 'registered')
            ->where('audition_results.accepted', 1)
            ->where('audition_results.acceptance_abbr', 'mx')
            ->select('audition_results.total')
            ->orderBy('candidates.id')
            ->count('candidates.id');

80 rows

DB::table('candidates')
            ->join('audition_results', 'candidates.id', '=', 'audition_results.candidate_id')
            ->join('students', 'candidates.student_id', '=', 'students.id')
            ->join('users', 'students.user_id', '=', 'users.id')
//introduce left-join
            ->leftJoin('phone_numbers AS homePhone', 'users.id','=', 'homePhone.user_id')
            ->where('candidates.version_id', $this->versionId)
            ->where('candidates.status', 'registered')
            ->where('audition_results.accepted', 1)
            ->where('audition_results.acceptance_abbr', 'mx')
//qualify left-join
            ->where('homePhone.phone_type', 'home')
            ->select('audition_results.total')
            ->orderBy('candidates.id')
            ->count('candidates.id');
0 likes
2 replies
LaryAI's avatar
LaryAI
AI
Best Answer
Level 58

The issue you're encountering is due to the way you're applying the where clause on the homePhone.phone_type field. When you use a LEFT JOIN, it will return all rows from the left table (in this case, the result of the previous joins) and the matched rows from the right table (phone_numbers). If there is no match, the result is NULL for columns from the right table.

However, when you add a where condition on a column from the right table (like homePhone.phone_type), it effectively turns the LEFT JOIN into an INNER JOIN because it filters out rows where homePhone.phone_type is NULL.

To fix this, you should move the condition on homePhone.phone_type to the on clause of the leftJoin. Here's how you can adjust your query:

DB::table('candidates')
    ->join('audition_results', 'candidates.id', '=', 'audition_results.candidate_id')
    ->join('students', 'candidates.student_id', '=', 'students.id')
    ->join('users', 'students.user_id', '=', 'users.id')
    ->leftJoin('phone_numbers AS homePhone', function($join) {
        $join->on('users.id', '=', 'homePhone.user_id')
             ->where('homePhone.phone_type', 'home');
    })
    ->where('candidates.version_id', $this->versionId)
    ->where('candidates.status', 'registered')
    ->where('audition_results.accepted', 1)
    ->where('audition_results.acceptance_abbr', 'mx')
    ->select('audition_results.total')
    ->orderBy('candidates.id')
    ->count('candidates.id');

By moving the where('homePhone.phone_type', 'home') condition into the on clause of the leftJoin, you ensure that the join condition is applied correctly without filtering out rows where homePhone is NULL. This should give you the expected number of rows.

tisuchi's avatar

@rretzko Just out of curiosity, isn't that possible to achieve the same things with eloquent relationship? Won't it be a more clean approach?

Please or to participate in this conversation.