I will have to write an inner join with custom SELECT statement in it and one of the conditions required is to get those rows which have matching null values in the columns, I was able to get the relationship in raw sql statment with (a.<col> = b.<col> OR (a.<col> IS NULL AND b.<col> IS NULL)) but I do not know how to write it using Laravel Eloquent. What is the inner join with OR in Laravel Eloquent? I have tried with $join->on('a.<col>', '=', 'b.<col>')->where('a.<col>', '=', DB::raw(NULL))->where('b.<col>', '=', DB::raw(NULL)); but it doesn't give me the expected result.
Related
This raw query is working well with two commented lines.
$q = DB::table('stock_items')
->selectRaw('stock_parts.title')
->selectRaw('COUNT(*) as qtyAvailable')
->selectRaw('SUM(shipments.item_cost) as totalValue')
//->selectRaw('stock_alerts.minimum AS minimum')
->join('stock_parts', 'stock_items.stock_part_id', '=', 'stock_parts.id')
->join('shipments', 'shipments.id', '=', 'stock_items.shipment_id')
//->leftJoin('stock_alerts', 'stock_alerts.stock_part_id', '=', 'stock_items.stock_part_id')
->whereNull('stock_items.status')
->where('stock_items.current_stock_id', '=', $stockId)
->groupBy('stock_parts.id')
->get();
The commented lines are needed to get information from another table.
In raw SQL I was using LEFT OUTER JOIN and it works.
Uncommenting those lines it shows this error:
SQLSTATE[42000]: Syntax error or access violation: 1055
Expression #4 of SELECT list is not in GROUP BY clause
and contains nonaggregated column 'rdphone-dev.stock_alerts.minimum'
which is not functionally dependent on columns in GROUP BY clause;
this is incompatible with sql_mode=only_full_group_by (SQL: select stock_parts.title, COUNT(*) as qtyAvailable, SUM(shipments.item_cost) as totalValue, stock_alerts.minimum AS minimum from `stock_items` inner join `stock_parts` on `stock_items`.`stock_part_id` = `stock_parts`.`id` inner join `shipments` on `shipments`.`id` = `stock_items`.`shipment_id` left join `stock_alerts` on `stock_alerts`.`stock_part_id` = `stock_items`.`stock_part_id` where `stock_items`.`status` is null and `stock_items`.`current_stock_id` = 1 group by `stock_parts`.`id`)",
What is the correct way to do LEFT OUTER JOIN in Laravel 5.6?
Every field used in the select has to be included in the group by, I added the minimum column in the groupBy.
$q = DB::table('stock_items')
->selectRaw('stock_parts.title')
->selectRaw('COUNT(*) as qtyAvailable')
->selectRaw('SUM(shipments.item_cost) as totalValue')
->selectRaw('stock_alerts.minimum AS minimum')
->join('stock_parts', 'stock_items.stock_part_id', '=', 'stock_parts.id')
->join('shipments', 'shipments.id', '=', 'stock_items.shipment_id')
->leftJoin('stock_alerts', 'stock_alerts.stock_part_id', '=', 'stock_items.stock_part_id')
->whereNull('stock_items.status')
->where('stock_items.current_stock_id', '=', $stockId)
->groupBy('stock_parts.id', 'minimum')
->get();
I have belongsToMany relationship between items and vehicle.
items can be assigned to multiple vehicles. same vehicle can b assigned to multiple items. so my pivot table item_vehicle have extra column date which will show that when vehicle is assigned to item.
here is my query.
select `items`.`id`, `items`.`name`, `items`.`area` as `total_area`,
`item_vehicle`.`date`, `vehicles`.`name` as `vehicle_name`,
SUM(parcel_vehicle.area) as processed_area
from `parcels`
inner join `item_vehicle` on `item_vehicle`.`p_id` = `items`.`id`
inner join `vehicles` on `item_vehicle`.`t_id` = `vehicles`.`id`
where `item_vehicle`.`date` < '?' and `items`.`processed` = ? and `vehicles`.`name`=?
group by items.id
what will be the eloquent way of doing this
Item::with(['vehicle'=>function($q){$q->wherePivot('date','<','2019/2/12');}])->whereHas('vehicle',function($q){$q->where('vehicles.id','2');})->where('processed',1)->where('id',4)
->get();
my concerns is it should run only one query
$parcels = Parcel::join('item_vehicle', 'item_vehicle.pid', '=' ,'items.id')
->join('vehicles', 'vehicles.id', '=' ,'item_vehicle.t_id')
->where('item_vehicle.date', '<', $date)
->where('items.processed', $processed)
->where('vehicles.name', $vehicleName)
->select(
'items.id',
'items.name',
\DB::raw('items.area as total_area'),
'item_vehicle.date',
\DB::raw('vehicles.name as vehicle_name'),
\DB::raw('SUM(parcel_vehicle.area) as processed_area')
)
->groupBy('items.id')
->get();
However, you have non-aggregated columns in select and you are doing group by. To make this work you might need to disable mysql's only_full_group_by mode
I need a query where I want to join tables, on 2 conditions in OR. Out of these 2 condition is to check whether the column IS NULL.
$query->select('users.*', 'o.name', 'r.name')
->join('owners as o', 'users.owner_id', '=', 'o.id')
->join('residents as r', 'users.resident_id', '=', 'r.id');
In the above query I also want to check if the users.resident_id IS NULL i.e., users.resident_id = r.id OR users.resident_id IS NULL.
Thanks for your time and help in advance.
i haven't try this..
how about use "right join" sql..
from w3school..
SQL RIGHT JOIN Keyword. The RIGHT JOIN keyword returns all records from the right table (table2), and the matched records from the left table (table1). The result is NULL from the left side, when there is no match.
if this not working then use "whereIn"..
select all id with null data first, then select all id from join.. then you can use whereIn to select all data with id from data1 and data2..
I am using laravel 5.3 and I have some left join query with error in laravel query method.
This is my normal query
SELECT bran.branchName,sch.schoolName From m_schoolbranch bran
LEFT JOIN m_students stu ON stu.schoolNo=bran.schoolNo AND stu.branchNo=bran.branchNo
LEFT JOIN m_school sch ON sch.schoolNo=stu.schoolNo where stu.userNo='0000000001';
And this is my new laravel Query
DB::table('m_schoolbranch')
->join('m_students', 'm_schoolbranch.schoolNo', '=', 'm_students.schoolNo')
->join('m_students', 'm_schoolbranch.branchNo', '=', 'm_students.branchNo')
->join('m_school', 'm_schoolbranch.schoolNo', '=', 'm_school.schoolNo')
->select('m_school.schoolName', 'm_schoolbranch.branchName')
->where('m_students.userNo',$userNo)
->get();
In these query I need to match two column in table m_students so I put like this
->join('m_students', 'm_schoolbranch.branchNo', '=', 'm_students.branchNo')
But i show error...
Tables in the query need to have unique names, otherwise the DB has no way of knowing which m_schoolbranch should be used when evaluating m_schoolbranch.schoolNo.
You could use unique table aliases in your join statements but I recommend using multiple conditions on the join. Just like you use in your original SQL query. See here: https://stackoverflow.com/a/20732468/4437888
DB::table('m_schoolbranch')
->join('m_students', function($join)
{
$join->on('m_schoolbranch.schoolNo', '=', 'm_students.schoolNo');
$join->on('m_schoolbranch.branchNo', '=', 'm_students.branchNo');
})
->join('m_school', 'm_schoolbranch.schoolNo', '=', 'm_school.schoolNo')
->select('m_school.schoolName', 'm_schoolbranch.branchName')
->where('m_students.userNo',$userNo)
->get();
I have a query that makes use of multiple joins:
public function scopePurchased($query, $userId)
{
return $query
->join('products','characters.id','=','products.productable_id')
->join('bundle_product','bundle_product.product_id','=','products.id')
->join('bundles','bundles.id','=','bundle_product.bundle_id')
->join('purchases','purchases.bundle_id','=','bundles.id')
->join('users','purchases.user_id','=','users.id')
->whereNull('purchases.deleted_at')
->where('purchases.refunded', false)
->where('products.productable_type', '=', get_class($this))
->where('users.id','=',$userId)
->groupBy('characters.id')
->orderBy('characters.title', 'ASC');
}
And I want to retrieve an array of ID's from this query to use in another scope so:
$query->purchased($userID)->lists('id')
My initial thought was to use lists('id') which complained about an ambiguous query on the ID.
Column 'id' in field list is ambiguous
(
SQL: select `id` from `characters`
inner join `products` on `characters`.`id` = `products`.`productable_id`
inner join `bundle_product` on `bundle_product`.`product_id` = `products`.`id`
inner join `bundles` on `bundles`.`id` = `bundle_product`.`bundle_id`
inner join `purchases` on `purchases`.`bundle_id` = `bundles`.`id`
inner join `users` on `purchases`.`user_id` = `users`.`id`
where `characters`.`deleted_at` is null
and `purchases`.`deleted_at` is null
and `purchases`.`refunded` = 0
and `products`.`productable_type` = Character and `users`.`id` = 1
group by `characters`.`id`
order by `characters`.`title` asc
)
Makes sense, fair enough so I changed the lists to
$query->purchased($userID)->lists('characters.id')
Thinking that naming the table and column should fix it but finding that the lists function drops the 'character.' part and so having the same error.
It appear that lists may not use a dot notation, bring me to my question... Can I escape the dot notation or is there another way to get the list of ID's as an array?
Many thanks
You can alias the column name before using lists:
$query->purchased($userID)->select('characters.id as _id')->lists('_id');
This will avoid any column name conflicts.