how to join 3 tables using laravel eloquent? - laravel

my table
Code:
function viewPDF()
{
$reports = Report::join('president_report', 'reports.id', '=', 'president_report.report_id')
->join('president_report', 'presidents.id', '=', 'president_report.president_id')->
select('reports.*')->where('president_report.report_id')
->filter()->latest()->get();
$pdf = PDF::loadView('reports.test1', ['reports' => $reports]);
return $pdf->stream('reports.pdf');
}
Error:
SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique
table/alias: 'president_report' (SQL: select * from reports inner
join president_report on reports.id =
president_report.report_id inner join president_report on
presidents.id = president_report.president_id where
president_report.report_id is null order by created_at desc)

Use separate aliases for the two joins with the president_reports table:
function viewPDF() {
$reports = Report::join('president_report pr1', 'reports.id', '=', 'pr1.report_id')
->join('president_report pr2', 'presidents.id', '=', 'pr2.president_id')->
select('reports.*')->where('pr1.report_id')
->filter()->latest()->get();
$pdf = PDF::loadView('reports.test1', ['reports' => $reports]);
return $pdf->stream('reports.pdf');
}
Note that the second join looks suspicious to me, because I don't see where the presidents table is getting included in the join query. But the general solution to use problem is to alias president_report differently for the two joins.

Related

how to fetch data from 3 different table in laravel using advance join

I have 3 table
This is my first table cart_items .👇🏻
This is my second table ecomm_products.👇🏻
This is my Third table ecomm_sellers.👇🏻
$result = DB::table('cart_items')
->join('ecomm_products','ecomm_sellers',function($join){
$join->on('ecomm_products.id','=','cart_items.product_id')->where('cart_items.order_id','=',1);
$join->on('ecomm_products.seller_id','=','ecomm_sellers.id');
})
->where('cart_items.user_id','=',Auth::user()->id)
->select('ecomm_products.product_name','ecomm_products.showcase_image','ecomm_products.selling_price','cart_items.quantity','cart_items.id')
->get();
But I am getting an error ⛔⛔⛔
strtolower(): Argument #1 ($string) must be of type string, Closure given
When I have not included 3 tables (ecomm_sellers) till the query is running good but when I add it sends me some errors.
The question is: Why I am getting this error and why this query is not working, What else I can add so that my query working fine.
You cannot join two tables in by passing the table names as arguments to join. If you check the API documentation of the join method you can see that its signature is:
$this join(string $table, Closure|string $first, string|null $operator = null, string|null $second = null, string $type = 'inner', bool $where = false)
so you can only join two tables at a time and if you want to join more than two tables you chain another call to the join method.
try this:
$result = DB::table('cart_items')
->join('ecomm_products', 'ecomm_products.id', '=', 'cart_items.product_id')
->join('ecomm_sellers' , 'ecomm_products.seller_id', '=', 'ecomm_sellers.id')
->where('cart_items.order_id', '=', 1)
->where('cart_items.user_id', '=', Auth::user()->id)
->select([
'ecomm_products.product_name',
'ecomm_products.showcase_image',
'ecomm_products.selling_price',
'cart_items.quantity',
'cart_items.id'
])
->get();
You can find examples for Laravel query builder joins here

How to do LEFT OUTER JOIN in Laravel raw expression

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();

Laravel 5.2 orderBy relation withCount results in SQL error because of failed attempt to get column instead of count

The goal is to sort my campaigns by views in my filtration, which is why i have an analytics table with relations to my campaigns
My campaign model (The DB name is "ads"):
public function views() {
return $this->hasMany('App\Analytic', 'foreign_id', 'id')->where('foreign_type', '=', 'campaign');
}
The controller of my filtration:
$query = Ad::withCount('views')->with('tags');
$query->where("is_active", "=", 1);
$query->where("status", "=", 1);
$query->orderBy('views_count', 'DESC');
$campaigns = $query->get();
Now the reason for not writing it without the $query-> part, is because the query has lots of if statements depending on filtration settings.
The error im getting:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'views_count' in 'order clause' (SQL: select count(*) as aggregate from `ads` where `is_active` = 1 and `status` = 1 and `from_year` >= 7 and `to_year` <= 88 and `price` >= 1000 and `price` <= 64000 order by `views_count` desc)
The error is it tries to fetch a column, but i can't figuere out why.
If i try to access $campaign->views_count in my blade template, it shows the count just fine.
Thank you for your time, i hope someone can tell me what I'm doing wrong here.
The error you're getting is a result of a count() method not a get().
something like this
$query = Ad::withCount('views')->with('tags');
$query->where("is_active", "=", 1);
$query->where("status", "=", 1);
$query->orderBy('views_count', 'DESC');
$campaignCount = $query->count();
wich replaces the complex select part with:
select count(*) as aggregate
if you need the count() and the get(), do it like this:
$query = Ad::withCount('views')->with('tags');
$query->where("is_active", "=", 1);
$query->where("status", "=", 1);
$campaignCount = $query->count();
$query->orderBy('views_count', 'DESC');
$campaigns = $query->get();

Convert SQL to Laravel Eloquent Statement

I've been working on a few tables where through a rather complex relationship (that I'm trying to clean up, but I still need reports made from the data through my Laravel).
At the moment, I can pull the data using the following SQL query to my MySQL database:
SELECT
customers.id,
customers.customer_name,
SUM(shipments.balance) AS shipmentBalance
FROM customers
LEFT JOIN shipments
ON customers.id = shipments.bill_to
AND balance > (SELECT IFNULL(SUM(payments_distributions.amount),0)
FROM payments_distributions
WHERE payments_distributions.shipment_id = pro_number)
GROUP BY customers.id, customers.customer_name
ORDER BY shipmentBalance DESC
LIMIT 5;
I'm just not sure how to rewrite it properly into the whereRaw or DB::raw statements that Laravel Eloquent requires, as my previous attempts have failed.
Update
Here is the closest solution I have tried:
DB::table('customers')
->select('customers', DB::raw('SUM(shipments.balance) AS shipmentBalance'))
->leftJoin(
DB::raw('
(select shipments
ON customers.id = shipments.bill_to
AND balance > (SELECT IFNULL(SUM(payments_distributions.amount),0)
FROM payments_distributions
WHERE payments_distributions.shipment_id = pro_number)'))
->groupBy('customers.id')
->orderByRaw('shipmentBalance DESC')
->limit(5)
->get();
Update 2
Edit for Dom:
Using everything as it stands with your answer, I get the following response:
SQLSTATE[42S22]: Column not found: 1054 Unknown column '' in 'on clause' (SQL: select customers.id, customers.customer_name,SUM(s.balance) AS shipmentBalance from `customers` left join `shipments` as `s` on `customers`.`id` = `s`.`bill_to` and s.balance > (SELECT IFNULL(SUM(payments_distributions.amount),0) FROM payments_distributions WHERE payments_distributions.shipment_id = s.pro_number) = `` group by `customers`.`id`, `customers`.`customer_name` order by SUM(s.balance) DESC limit 5)
But if I remove this section, it brings up the page and the customers (though in the wrong order as I have removed one of the necessary components:
$join->on(DB::raw('s.balance >
(SELECT IFNULL(SUM(payments_distributions.amount),0)
FROM payments_distributions
WHERE payments_distributions.shipment_id = s.pro_number)
'));
Is there anything I can provide you with to get this specific statement to work with your entire answer?
Use this:
DB::table('customers')
->select('customers.id', 'customers.customer_name', DB::raw('SUM(shipments.balance) AS shipmentBalance'))
->leftJoin('shipments', function($join) {
$join->on('customers.id', 'shipments.bill_to')
->where('balance', '>', function($query) {
$query->selectRaw('IFNULL(SUM(payments_distributions.amount),0)')
->from('payments_distributions')
->where('payments_distributions.shipment_id', DB::raw('pro_number'));
});
})
->groupBy('customers.id', 'customers.customer_name')
->orderByDesc('shipmentBalance')
->limit(5)
->get();
Without the Models containing relationships or being able to test on this specific project, this is the most eloquent way I can think of performing your task.
The benefit of starting with the Customer model is you will have a laravel collection and can paginate as needed. Also review the eloquent docs, they help you understand all the different options. Hope his helps.
P.S. Start by using your model in your controller or wherever you are placing this query with:
use App\Customer
The query
$theQuery = Customer::select(DB::raw('customers.id, customers.customer_name,SUM(s.balance) AS shipmentBalance'))
->leftJoin('shipments as s', function($join)
{
$join->on('customers.id', '=', 's.bill_to');
$join->on(DB::raw('s.balance >
(SELECT IFNULL(SUM(payments_distributions.amount),0)
FROM payments_distributions
WHERE payments_distributions.shipment_id = s.pro_number)
'));
})
->groupBy('customers.id', 'customers.customer_name')
->orderByRaw('SUM(s.balance) DESC')
->limit(5)
->get();

MySql Query error in Laravel

I am using laravel 5.4. When trying to run
select * from `users` inner join `addprojects` on `users`.`emp_id` = `addprojects`.`emp_id` where `emp_id` = $emp_id)"
It produces:
"SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'emp_id'
in where clause is ambiguous (SQL: select * from users inner join
addprojects on users.emp_id = addprojects.emp_id where
emp_id = $emp_id)"
$emp_id= Auth::user()->emp_id;
$projects_for_emp = DB::table('users')->join('addprojects', 'users.emp_id', '=', 'addprojects.emp_id')->where('emp_id', '$emp_id')->get();
emp_id in both tables , so can use users.emp_id or addprojects.emp_id
->where('users.emp_id', '=', $emp_id)
You have specified column name which exists in both tables, so use users.emp_id or addprojects.emp_id doesn't matter which one
Example:
$emp_id= Auth::user()->emp_id;
$projects_for_emp = DB::table('users')
->join('addprojects', 'users.emp_id', '=', 'addprojects.emp_id')
->where('users.emp_id', '$emp_id')
->get();
Because both users and addprojects tables have same named field "emp_id".
You can change your code like following.
$emp_id= Auth::user()->emp_id;
$projects_for_emp = DB::table('users')
->join('addprojects', 'users.emp_id', '=', 'addprojects.emp_id')
->where('users.emp_id', $emp_id)
->get();

Resources