two syntax problems with join and left-join in the same query - mysql

I have this code to create a collection:
$rank_entities_by_capacity = Entity::join('entity_capacitytypes', function($q){
$q->on('entitys_id', '=', 'entities.id');
$q->where('capacitytypes_id','=', '23');
})->
leftJoin('user_attitudes', function($q){
$q->on('entity_id', '=', 'entities.id');
$q->where('item_type', '=', 'entity');
})
->selectRaw('entities.*, SUM(user_attitudes.importance) AS importance')
->groupBy('entities.id')
->orderBy('importance', 'desc')
->take(6)
->get();
First problem:
1052 Column 'entity_id' in on clause is ambiguous:
[2015-01-01 13:22:28] production.ERROR: FATAL DATABASE ERROR: 500 = SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'entity_id' in on clause is ambiguous (SQL: select entities.*, SUM(user_attitudes.importance) AS importance from entities inner join entity_capacitytypes on entity_id = entities.id and capacitytypes_id = 23 left join user_attitudes on entity_id = entities.id and item_type = entity group by entities.id order by importance desc limit 6) [] []
I traded over an hour for finding a trick to bypass the problem:
I was forced to change column name in table entity_capacitytypes from entity_id (it was causing problems) to entitys_id just in order to avoid this error.
Now my database names are not consistent. Any other way to avoid the error?
Problem 2:
If I add this part to the query, and try to use a previously perfectly working variable in the where line
join('entity_capacitytypes', function($q){
$q->on('entitys_id', '=', 'entities.id');
$q->where('capacitytypes_id','=', $capacity);
})->
I get this error:
Undefined variable: capacity
How make the variable work?
My solution: avoidance again.
I ould't fix join, so I used a relation defined in Capacitytype model:
public function entities()
{
return $this->belongsToMany('Entity', 'entity_capacitytypes', 'capacitytypes_id', 'entitys_id');
}
and instead using join, I accessed Entity from another model
$rank_entities_by_capacity = Capacitytype::find($capacity)->entities()->
leftJoin('user_attitudes', function($q){
$q->on('entity_id', '=', 'entities.id');
$q->where('item_type', '=', 'entity');
})
->selectRaw('entities.*, SUM(user_attitudes.importance) AS importance')
->groupBy('entities.id')
->orderBy('importance', 'desc')
->take(6)
->get();
To do:
make the variable work in join

Problem 1
To fix the "ambiguous column" problem you only need to specify the full column name including the table
entity_capacitytypes.entity_id instead of only entity_id
Problem 2
To use a local variable like $capacity inside a closure (aka anonymous function) you need to inject them with use
join('entity_capacitytypes', function($q) use ($capacity){
$q->on('entitys_id', '=', 'entities.id');
$q->where('capacitytypes_id','=', $capacity);
})

Related

groupBy on laravel

$tren = DB::table('suka')
->join('buku', 'buku.ISBN', '=', 'suka.ISBN')
->join('user', 'user.id_user', '=', 'suka.id_user')
->raw('count(*) as total')
->groupBy('suka.ISBN')
->orderBy('maximum')
->LIMIT(2)
->get();
I want to group a join table by ISBN and then find the maximum count of them and take 2 of the most.
here is the error message
Call to undefined method Illuminate\Database\Query\Expression::groupBy()
There is more than one ISBN column in the result set (because it exists in multiple tables). You should specify which table's ISBN column you want to group by in your group by call.
Also, try calling selectRaw instead of raw:
->selectRaw('count(*) as total')
You can read more about raw queries in this documentation.

groupBy is expecting more table columns in many to many relationship

I'm trying to get all the roles permission which has a many to many relationship. I want to get all the permissions of a single role. Here I'm trying to use groupBy but it gives me error.
$search_role = DB::table('roles')
->join('roles_permissions','roles_permissions.role_id','roles.id')
->join('permissions','permissions.id','roles_permissions.permission_id')
->where('roles.name', 'like', "%$request->searcher%")
->orWhere('permissions.name', 'like', "%$request->searcher%")
->select('roles.name as role_name', 'permissions.name as permission_name','roles_permissions.*')
->groupBy('roles_permissions.role_id')
->get();
Error here:
roles_permissions.permission_id isn't in groupBy.
If I add that I get another column isn't in groupBy.
you don't have any aggregation operation in select statement. check my example
$search_role = DB::table('roles')
->join('roles_permissions','roles_permissions.role_id','roles.id')
->join('permissions','permissions.id','roles_permissions.permission_id')
->where('roles.name', 'like', "%$request->searcher%")
->orWhere('permissions.name', 'like', "%$request->searcher%")
->select('role_id', DB::raw('count(*) as total')) //example
->groupBy('roles_permissions.role_id')
->get();
what you are trying to do does not makes sense. Group by does not work in that way.
SELECT role_id, count(*)
from roles
group by role_id
is valid
SELECT roles.*, count(*)
from roles
group by role_id
is not. in the latter case, you generally need to add every column which is not aggregated to group by statement

Mysql join selects multiple column best practice

I'm using Laravel Query Builder and my join statement working perfectly.
User table columns:
name|email|phone|gender
School_Abouts table columns:
courses|boards|contact|location|teachers
Currently I do the select query as below:
$school=User::join('school_abouts', 'users.id', '=', 'school_abouts.school_id')
->where('users.id',$id)
->select('users.name',
'users.email',
'users.phone',
'school_abouts.courses',
'school_abouts.boards',
'school_abouts.contact',
'school_abouts.location',
'school_abouts.teachers')
->first();
To select the columns from school_about table I have to write table name multiple times. But is there any way to pass an array of columns instead? I tried this but failed:
->select('users.name',
'users.email',
'users.phone',
'school_abouts'.[courses,boards,location,contact,teachers],
)
You can safely remove table name from columns as there is no column name common in both tables but else, as I see, you are trying to get almost all columns from both tables which could be simplified using *:
$school = User::join('school_abouts', 'users.id', '=', 'school_abouts.school_id')
->where('users.id', $id)
->select('users.*', 'school_abouts.*')
->first();
However, if you want to get some columns and their names could make an ambiguity then prefixing column names with table name is a must. To make it shorter you could use aliasing:
$school = User::join('school_abouts AS sa', 'users.id', '=', 'sa.school_id')
->where('users.id', $id)
->select('users.name',
'sa.courses',
'sa.boards',
'sa.contact',
'sa.location')
->first();

laravel multiple join conditions with integer values

I want to make a join with multiple conditions:
->join('filters', function($join) {
$join->on('filters.result_id', '=', 'results.id');
$join->on('filters.result_filter_id', '=', 2);
$join->on('filters.value', '>', 1);
})
This results in an error:
Unknown column '2' in 'on clause'
How can I use actual values in the join on condition without having eloquent interpret it as a column name? It works fine with the actual SQL query:
JOIN filters ON filters.result_id = results.id
AND filters.result_filter_id = 2
AND filters.value > 1
Replace on with where if you want to filter your join
If you would like to use a "where" style clause on your joins, you may use the where and orWhere methods on a join
->join('filters', function($join) {
$join->on('filters.result_id', '=', 'results.id')
->where('filters.result_filter_id', '=', 2)
->where('filters.value', '>', 1);
})
Documentation

How to select max aggregate within a subquery with a join in eloquent

I want to select the most recent entry but there are no timestamps(created_at) it can be identified by selecting the max on the primary key. The problem is to this within a subquery and tables needs to be joined.
The query is like:
$prodarr = DB::table('onhand_inventory')
->leftJoin('mapping', 'onhand_inventory.sku', '=', 'mapping.sku')
->where('mapping.mid', function ($query) {
$query->select('mapping.mid')->from('mapping')
->whereRaw('onhand_inventory.sku = mapping.sku')
->max('mapping.mid');
})->leftJoin('order_products', 'order_products.sku', '=', 'onhand_inventory.sku')
->leftJoin('vendors', 'mapping.v_id', '=', 'vendors.vid')
->where('onhand_inventory.shipped_with_box', 0)
->groupBy('onhand_inventory.inv_id')
->orderBy('onhand_inventory.inv_id')
->get();
On executing the above query following error is thrown
Column not found: 1054 Unknown column 'onhand_inventory.sku' in 'where clause'
How to get the onhand_inventory's data to be compared with the mapping's inside the subquery.
You already joined the mapping table so you dont need the sub query.
$prodarr = DB::table('onhand_inventory')
->leftJoin('mapping', 'onhand_inventory.sku', '=', 'mapping.sku')
->leftJoin('order_products', 'order_products.sku', '=', 'onhand_inventory.sku')
->leftJoin('vendors', 'mapping.v_id', '=', 'vendors.vid')
->where('onhand_inventory.shipped_with_box', 0)
->orderBy('mapping.mid', 'desc')
->groupBy('onhand_inventory.inv_id')
->orderBy('onhand_inventory.inv_id')
->limit(1)
->get();
I didnt run the code but i hope this will help.