Nurdin
Nurdin

Reputation: 23891

Laravel - Syntax error or access violation: 1066 Not unique table/alias:

I got this error message when trying to join multiple tables

Illuminate \ Database \ QueryException (42000)
SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: 'users' (SQL: select * from `prescriptions` inner join `doctors` on `prescriptions`.`doctor_id` = `doctors`.`id` inner join `users` on `doctors`.`user_id` = `users`.`id` inner join `patients` on `prescriptions`.`patient_id` = `patients`.`id` inner join `users` on `patients`.`user_id` = `users`.`id` inner join `pharmacies` on `prescriptions`.`patient_id` = `pharmacies`.`id` inner join `users` on `pharmacies`.`user_id` = `users`.`id` where `prescriptions`.`pharmacy_id` = 1)

My code is like this

$prescriptions = DB::table('prescriptions') 
        ->join('doctors', 'prescriptions.doctor_id', '=', 'doctors.id')
        ->join('users', 'doctors.user_id', '=', 'users.id')
        ->join('patients', 'prescriptions.patient_id', '=', 'patients.id')
        ->join('users', 'patients.user_id', '=', 'users.id')
        ->join('pharmacies', 'prescriptions.patient_id', '=', 'pharmacies.id')
        ->join('users', 'pharmacies.user_id', '=', 'users.id')
        ->where('prescriptions.pharmacy_id',$pharmacy->id)
        ->get();

My ERD diagram

enter image description here

Upvotes: 1

Views: 2294

Answers (2)

Jonathon
Jonathon

Reputation: 16333

As others have correctly pointed out, the problem is that you've joined in the users table three times but since they have not been aliased, your database is unable to distinguish which table you mean when you try to use it in any way. The solution would be to alias each users table when you join them. For example:

$prescriptions = DB::table('prescriptions') 
    ->join('doctors', 'prescriptions.doctor_id', '=', 'doctors.id')
    ->join('users as du', 'doctors.user_id', '=', 'du.id')
    ->join('patients', 'prescriptions.patient_id', '=', 'patients.id')
    ->join('users as pu', 'patients.user_id', '=', 'pu.id')
    ...
    ->get([
        'du.name as doctor_name',
        'pu.name as patient_name',
        'prescriptions.description as description'
    ]);

To grab the doctor's name for example:

foreach ($prescriptions as $prescription) {
    echo $prescription->doctor_name;
}

However, I would suggest doing this with Eloquent instead:

$prescriptions = Prescription::where('pharmacy_id', $pharmacyId)
    ->with('patient', 'patient.user', 'doctor', 'doctor.user');

This will effectively run one query to select all prescriptions by the given pharmacy_id and then it will run subsequent queries to eagerly load in the associated patients (and their associated users) and those doctors (and their associated users).

If you don't need to load the pharmacy name or any other information about the pharmacy or its associated user, then you needn't bother load them in. If you do, it's as simple as following the above format and adding them to the ->with() which will result in them being eager loaded.

After doing the above, you can access a patient's name like this:

foreach ($prescriptions as $prescription) {
    echo $prescription->patient->user->name;
}

This of course assumes you have your relations all correctly set up.

Upvotes: 3

Demonyowh
Demonyowh

Reputation: 1672

this is because you're using the same alias for 3 joins .. this will do:

$prescriptions = DB::table('prescriptions') 
    ->leftJoin('doctors', function($join){
        $join->join('users as a', 'doctors.user_id', '=', 'a.id');
    })
    ->leftJoin('patients', function($join){
        $join->join('users as b', 'patients.user_id', '=', 'b.id');
    })
    ->join('pharmacies', function($join){
        $join->join('users as c', 'pharmacies.user_id', '=', 'c.id');
    })
    ->where('prescriptions.pharmacy_id',$pharmacy->id)
    ->get();

Upvotes: -1

Related Questions