How to build a Laravel query with joins and sum? - php

I am trying to configure a query within a Laravel app that is equivalent to this:
SELECT SUM(balance), name FROM db.statement_versions
INNER JOIN statements ON statement_versions.statement_id = statements.id
INNER JOIN accounts ON statements.account_id = accounts.id
GROUP BY name;
This query works when I run it in MySQL Workbench, but when I try to translate it into PHP with the Laravel query builder I am getting an error. What I ultimately want is to return all accounts with their summed balance of statement_versions.balance. Here is my code right now:
public static function query(LensRequest $request, $query)
{
return $request->withOrdering($request->withFilters(
$query->select('accounts.name')->sum('statement_versions.balance')
->join('statements', 'statement_versions.statement_id', '=', 'statements.id')
->join('accounts', 'statements.account_id', '=', 'accounts.id')
->orderBy('balance', 'desc')
->groupBy('statement_versions.balance', 'accounts.name')
));
}
I have tried a couple different variations of this, but I get the error SQLSTATE[42S22]: Column not found: 1054 Unknown column 'statement_versions.balance' in 'field list'. How can I solve this and get the query working correctly?

Not having your tables it will be a bit hard, but I hope that this will give you a path to what you want to achieve, it might be luck that it will work from the first shot :)
DB::table('statement_versions as sv')
->select([
'name',
DB::raw('sum(balance) as total')
])
->join('statements as s', 'sv.statement_id', '=', 's.id')
->join('accounts as a', 's.account_id', '=', 'a.id')
->groupBy('name');

Related

laravel query problem using join, what is missing?

first of all Im not good at english and im new using laravel framework. Im developing some school site for thesis purposes. And I think this might be a chance for me to learn laravel since many developers recommends laravel.
back to my problem hehe
This query runs right.
$questions = DB::table('questions')
->select('questions.id','questions.role','questions.postBody', 'questions.classCode', 'questions.postedById', 'questions.created_at', 'classroom.classroomName','classroom.icon','users.picture', 'students.firstName', 'students.middleName', 'students.lastName', 'students.suffix','students.studentNumber')
->join('classroom', 'classroom.classCode', '=', 'questions.classCode')
->join('users', 'users.id', '=', 'questions.postedById')
->join('students', 'students.email' , '=', 'users.email')
->orderBy('questions.created_at', 'DESC')
->skip($request->page - 5)
->take($request->page)
->get();
and when I adding other table ("teacher") i got no returns. This is the example of my query trying to join 'teacher' table and in here, im trying to select email of teacher
$questions = DB::table('questions')
->select('questions.id','questions.role','questions.postBody', 'questions.classCode', 'questions.postedById', 'questions.created_at', 'classroom.classroomName','classroom.icon','users.picture', 'students.firstName', 'students.middleName', 'students.lastName', 'students.suffix','students.studentNumber','teacher.email')
->join('classroom', 'classroom.classCode', '=', 'questions.classCode')
->join('users', 'users.id', '=', 'questions.postedById')
->join('students', 'students.email' , '=', 'users.email')
->join('teacher', 'teacher.email' , '=', 'users.email')
->orderBy('questions.created_at', 'DESC')
->skip($request->page - 5)
->take($request->page)
->get();
sorry for my bad english.
Can anyone help me? Thank you very much!
The problem is that after your first inner join there are only useres left that are also students. Because inner join is taking the cut-set of the joined tables:
https://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins
In the next innerjoin you are trying to get the cut-set of email addresses that are in the students and also teacher table. This will probably always be empty.
I recommend that you look up DB joins and I would use leftJoin for your use case.
->leftJoin('students', 'students.email' , '=', 'users.email')
->leftJoin('teacher', 'teacher.email' , '=', 'users.email')
Here are some good answers on the topic:
What's the difference between INNER JOIN, LEFT JOIN, RIGHT JOIN and FULL JOIN?

Laravel eloquent join multiple tables in the leftjoin

I'm new in laravel. I'm trying to join multiple tables in the left join however i facing the syntax error and i have no idea where goes wrong.
Code
$query = DB::table('sales')
->leftjoin('transactions AS trx', function ($join) {
$join->on('payment_methods AS payment', 'payment.id', '=', 'trx.payment_method_id');
$join->on('transactables', 'transactables.transaction_id', '=', 'transactions.id')
->whereNull('transactions.deleted_at')
->whereNull('transactables.deleted_at')
->where('transactable_type', '=', 'Sale')
->where('transactable_id', '=', 'sales.id');
})
The error meesage
Syntax error near '`payment_methods` as `payment` payment.id `=` and `transactions`.`deleted_at` is'
As the code above you can see. I'm trying to join table payment_methods and transactables within the transactions table.
Why don't you use the Eloquent like
$sales = Sale::with('transactions')->get();
Add relation in Sale model
public function transactions()
{
return $this->morphToMany('App\Transaction', 'transactable');
}
For more info, please refer to Laravel docs

Column not found: 1054 Unknown column - Laravel 5.1 Join

I have three tables. work_orders, customers, and aircraft. In the work_orders table there are two fields customer_id and aircraft_id. I'm trying to retrieve the customers and aircraft data through the use of join. I am getting an array of errors, but they all seem to be pointed in the same direction and that is that the table cannot be found.
Here is my WorkOrderController index:
public function index(WorkOrder $workorder)
{
$workorder_array = $workorder
->join('work_orders as work', 'work.aircraft_id', '=', 'aircraft.id')
->join('work_orders as workorder', 'workorder.customer_id', '=', 'customers.id')
->select('work_orders.opened_date', 'customers.mobile', 'aircraft.year')
->get();
return view('work-orders.index', compact('workorder_array'));
}
And with this I get the following error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'aircraft.id' in 'on clause' (SQL: select work_orders.opened_date from work_orders inner join work_orders as work on aircraft.id = work.aircraft_id inner join work_orders as workorder on workorder.customer_id = customers.id)
I've tried switching work.aircraft_id with aircraft.id, because the Laravel Docs show it in that order, but that doesn't make any difference either. The only way I can get rid of this error is to remove my join statements.
I had the wrong table in the join statement. Here's what I should have had:
public function index(WorkOrder $workorder)
{
$workorder_array = $workorder
->join('aircraft', 'work_orders.aircraft_id', '=', 'aircraft.id')
->join('customers', 'work_orders.customer_id', '=', 'customers.id')
->select('*')
->get();
return view('work-orders.index', compact('workorder_array'));
}

Laravel 5.1: handle joins with same column names

I'm trying to fetch following things from the database:
user name
user avatar_name
user avatar_filetype
complete conversation_messages
with the following query:
static public function getConversation($id)
{
$conversation = DB::table('conversation_messages')
->where('belongsTo', $id)
->join('users', 'conversation_messages.sender', '=', 'users.id')
->join('user_avatars', 'conversation_messages.sender', '=', 'user_avatars.id')
->select('users.name', 'conversation_messages.*', 'user_avatars.name', 'user_avatars.filetype')
->get();
return $conversation;
}
It works fine so far, but the avatar's column name is 'name' like the column name from the 'users' table.
So if I'm using this query the to get the output via $conversation->name, the avatar.name overwrites the users.name
Is there a way to rename the query output like the mysql "as" feature at laravel 5.1?
For example:
$conversation->avatarName
$conversation->userName
Meh okay.. i've found a simple solution here
->select('users.name as userName', 'conversation_messages.*', 'user_avatars.name as avatarName', 'user_avatars.filetype')
As you can mention I've added the requested "as-Feature" next to the table.columnName
Take a look at this example of trying to join three tables staffs, customers and bookings(pivot table).
$bookings = \DB::table('bookings')
->join('staffs', 'staffs.id' , '=', 'bookings.staff_id')
->join('customers', 'customers.id' , '=', 'bookings.customer_id')
->select('bookings.id', 'bookings.start_time', 'bookings.end_time', 'bookings.service', 'staffs.name as Staff-Name', 'customers.name as Customer-Name')
->orderBy('customers.name', 'desc')
->get();
return view('booking.index')
->with('bookings', $bookings);
I had the following problem, simplified example:
$result = Donation::join('user', 'user.id', '=', 'donation.user_id')->where('user.email', 'hello#papabello.com')->first();
$result is a collection of Donation models. BUT CAREFUL:
both tables, have a 'created_at' column. Now which created_at is displayed when doing $result->created_at ? i don't know. It seems that eloquent is doing an implicit select * when doing a join, returning models Donation but with additional attributes. created_at seems random. So what I really wanted, is a return of all Donation models of the user with email hello#papabello.com
solution is this:
$result = Donation::select('donation.*')->join('user', 'user.id', '=', 'donation.user_id')->where('user.email', 'hello#papabello.com')->first();
Yeah, simply rename the column on either table and it should work.
Also what you can do is, rename the user.name column to anything, also rename sender column of conversation_messages to id and perform a natural join.

Complicated Laravel Query leftjoin a made query

Right now I want to have the sum of Sueldo in a column grouped by idEmpleado of table recibo. Im not sure if I can put the DB::table inside the left join. if not how could I call that table in a query to make a join with the information of the empleado.
Here is what I have so far
$pagos = DB::table('empleado')
->leftJoin('empresa', 'empresa.idEmpresa', '=', 'empleado.emp_idEmpresa_FK')
->leftJoin('departamento', 'departamento.idDepartamento', '=', 'empleado.emp_idDeparameto_FK')
->leftJoin('tipoperiodo', 'tipoperiodo.idTipoPeriodo', '=', 'empleado.emp_idTipoPeriodo_FK')
->leftJoin(
DB::table('recibos')
->leftJoin('empleado', 'empleado.idEmpleado', '=', 'recibos.rec_idEmpleado_FK')
->select(DB::raw('idRecibos, rec_idEmpleado_FK, SUM(SueldoBase) as Restante'))
->groupBy('rec_idEmpleado_FK')
->get()
,'recibos', 'recibos.rec_idEmpleado_FK', '=', 'empleado.idEmpleado')
->select('idEmpleado', 'Nombre', 'Nombre_Depto', 'Nombre_Empresa', 'Puesto', 'SueldoBase', 'Restante')
->get();
I'm getting an error ErrorException with message :
Array to string conversion
I'm suppose its because I'm trying to make a leftjoin of a query im making there. Dunno Im knid of new to this. Any suggestions ?
With the help of the answer in the commnets I got to this Query,
DB::table('empleado')
->leftJoin('empresa', 'empresa.idEmpresa', '=', 'empleado.emp_idEmpresa_FK')
->leftJoin('departamento', 'departamento.idDepartamento', '=', 'empleado.emp_idDeparameto_FK')
->leftJoin('tipoperiodo', 'tipoperiodo.idTipoPeriodo', '=', 'empleado.emp_idTipoPeriodo_FK')
->leftjoin(
DB::raw('SELECT rec_idEmpleado_FK, SUM( SueldoBase ) AS Restante
FROM `recibos`
INNER JOIN empleado ON rec_idEmpleado_FK = idEmpleado
GROUP BY rec_idEmpleado_FK'),
function($join)
{
$join->on('idEmpleado', '=', 'rec_idEmpleado_FK');
})
->select('idEmpleado', 'Nombre', 'Nombre_Depto', 'Nombre_Empresa', 'Puesto', 'SueldoBase', 'Restante')
->get();
But still get the error:
check the manual that corresponds to your MySQL server version for the right syntax to use near
SELECT rec_idEmpleado_FK, SUM( SueldoBase ) AS Restante
FROM `recibos`
Any ideas why?
Ok I finally got the answer. I forgot to put the name to the inner query here is my answer. I hope it helps. I based my answer in the link that Chelsea gave me. Thanks
$pagos = DB::table('empleado')
->leftJoin('empresa', 'empresa.idEmpresa', '=', 'empleado.emp_idEmpresa_FK')
->leftJoin('departamento', 'departamento.idDepartamento', '=', 'empleado.emp_idDeparameto_FK')
->leftJoin('tipoperiodo', 'tipoperiodo.idTipoPeriodo', '=', 'empleado.emp_idTipoPeriodo_FK')
->leftjoin(
DB::raw('(SELECT rec_idEmpleado_FK, SUM( SueldoBase ) AS Restante
FROM `recibos`
INNER JOIN empleado ON rec_idEmpleado_FK = idEmpleado
GROUP BY rec_idEmpleado_FK) AS recibos1'),
function($join)
{
$join->on('idEmpleado', '=', 'rec_idEmpleado_FK');
})
->select('idEmpleado', 'Nombre', 'Nombre_Depto', 'Nombre_Empresa', 'Puesto', 'SueldoBase', 'Restante')
->get();

Categories