Eloquent in Laravel-Datatables, select in select? - laravel

I have 3 tables, the 1st has a FK from the 2nd, and the 2nd has a FK from the 3rd:
Table 1: [admin_demandas]
-------------------------
id_demanda| projec_id
-------------------------
Table 2: [admin_projec]
-------------------------
id_projec | sub_id
-------------------------
Table 3: [admin_sub]
-------------------------
id_sub | name
-------------------------
What I need is to get the 'name' from Table 3 but starting with the Model of the table 1.
I was trying something like this:
$data = AdminDemanda::select([
'id_demanda',
'admin_projec.sub_id AS sub_id',
'admin_sub.name AS name',])
->join('admin_projec', 'admin_demandas.projec_id', '=', 'admin_projec.id_projec')
->join('admin_sub', 'admin_projec.sub_id', '=', 'admin_sub.id_sub')
->get();
return Datatables::of($data)->make(true);
I've done my Datatables with only 1 JOIN (2 tables) but not sure how to do those 2 JOIN (3 tables). I got this error:
[Err] 1054 - Unknown column 'admin_projec.sub_id' in 'on clause'
What should I modify in my query?
Should I need to use query builder instead Eloquent, with a DB::raw() query?

Solved with this:
Inner join between three tables in mysql
it was simple... now in case anyone need it, my Datatable query is:
$datos = AdminDemanda::select([
'id_demanda',
'admin_dis.nombre AS nombre_dist',
'admin_sub.nombre AS nombre_subes',
'mes AS mes_demanda',
'admin_sistemas.nombre AS nombre_sistema',
'admin_demandas.demanda_mwh AS mwh'])
->join('admin_projec', 'admin_demandas.proyeccion_demanda_id', '=', 'admin_projec.id_proyeccion_demanda')
->join('admin_sub', 'admin_projec.subestacion_id', '=', 'admin_sub.id_subestacion')
->join('admin_dis', 'admin_projec.dist_id', '=', 'admin_dis.id_dist')
->join('admin_sistemas', 'admin_projec.sistema_id', '=', 'admin_sistemas.id_sistema')
->get();

You should edit your models
By exemple in AdminSub model
public function projec(){
return $this->hasMany(AdminProjec::class , 'sub_id');
}
You should be able to do
\AdminSub::first()->projec();
And continue by editing your AdminProjec model with the same kind of relationship
public function demandas(){
return $this->hasMany(AdminDemandas::class , 'projec_id');
}
And now you could try
//I do not remember which one will works
\AdminSub::first()->projec()->first()->demandas()->name
//or
\AdminSub::first()->projec()->first()->demandas()->get()->name

Related

Select Specific columns from multiple Table with with() and select ()

I have 2 tables test and goals. One goal has many tests. I would like to fetch data like below.
$tests = test::with('goals')
->where('Goal_id', $goal_id)
->select('test.id as id','goals.Goal_id as goal_id','test.mode as mode')
->get();
But I am getting error Illuminate\Database\QueryException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'goals.Goal_id' in 'field list'
The goals relation is being eager loaded in a separate query so you will not have access to goals.Goal_id in your main query builder, instead you can modify your with() clause to pick specific columns from eager loaded relation as with('goals:Goal_id,another_column')
$tests = test::with('goals:Goal_id')
->where('Goal_id', $goal_id)
->select(['test.id as id','test.mode as mode'])
->get();
This should work:
$tests = DB::table('test')
->select(['test.id as id', 'goals.Goal_id as goal_id', 'test.mode as mode'])
->join('goals', 'goals.id', '=', 'test.goal_id')
->where('Goal_id', $goal_id)
->get();

how to retrieve multiple table data with multiple criteria in laravel eloquent?

I want to retrieve data from 4 different table using laravel eloquent with multiple criteria.
an Overview of my table;
table 1
id
name
table 2
id
name
year
table1_id
table 3
id
name
description
table2_id
table 4
id
name
quarter
table3_id
below are their relations
table 1
hasMany -> table 2
table 2
belongsTo ->table1
HasMany->table2
table 3
belongsTo ->table2
HasMany->table3
table 4
belongsTo ->table3
I'd like to fetch the data by resource show with two parameters
and i tried this
$Report = Table1::whereHas('tabke1', function($query){
$query->where('year', 'like','%'.$year.'%');
})
->with('table2')->whereHas('table3', function($query){
$query->where('quarter', 'like', '%'.$quarters.'%');
})
->get();
but im receiving syntax error.
How can I retrieve the data from multiple table with multiple filter?
i tried this table query to understand more what i expect
SELECT `table1`.*, `table2`.*, `table3`.*, `table4`.*
FROM `table1`, `table2`, `table3`, `table4`
WHERE ((`table2`.* year = 2019) AND (`table4`.* quarter = 1))
I reckon there are two queries to achieve the results.
The first query is something like:
Table1::whereHas('table2', function ($query) {
$query->where('year', 2019);
})
->whereHas('table2.table3.table4', function ($query) {
$query->where('quarter', 1);
})
->get();
The second query is something like:
Table1::select('table1.*')
->join('table2', 'table1.id', '=', 'table2.table1_id')
->join('table3', 'table2.id', '=', 'table3.table2_id')
->join('table4', 'table3.id', '=', 'table4.table3_id')
->where('table2.year', 2019)
->where('table4.quarter', 1)
->distinct()
->get();
Regarding performance, I prefer the second query.

laravel get unique results filter by a column value

I have a user table in which there is column Membership Id. I need to fetch rows which do not have duplicate value for Membership Id column. For Example, this is my table structure
ID Name Membership Id
1 xxx 123
2 xxx 124
3 xxx 124
4 xxx 125
In output, I want to skip rows which have duplicate values for Membership Id and want to fetch only last row so output should be row 1,3,4 from above example
Use a subquery JOIN:
$join = User::select('membership_id', DB::raw('max(id) id'))
->groupBy('membership_id');
$sql = '(' . $join->toSql() . ') as latest';
$users = User::join(DB::raw($sql), function($join) {
$join->on('users.membership_id', 'latest.membership_id')
->on('users.id', 'latest.id');
})->get();
In Laravel 5.6.17 you can use joinSub():
$join = User::select('membership_id', DB::raw('max(id) id'))
->groupBy('membership_id');
$users = User::joinSub($join, 'latest', function($join) {
$join->on('users.membership_id', 'latest.membership_id')
->on('users.id', 'latest.id');
})->get();
Via eloquent
User::select('Membership_Id')->distinct()->get();
Vie db facade
DB::table('users')->select('Membership_Id')->distinct()->get();
For Eloquent
MyModel::distinct()->get(['column_name']);
for you
User::distinct()->get(['Membership Id']);

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

laravel 4.2 and join function

$options = table::join('table1', function($join) {
$join->on('table1.table_id','=','table.id');
$join->take(1);
})->get();
Is there a way to do this, i get error on take function.
the table and table1 has one to many relation, and i'd like to have on join just the first record of table1.
Thanks
Vincenzo

Resources