Laravel Controller: translating an SQL SELECT DISTINCT statement inside a function - sql

Table List:
Here is the SQL as mentioned in the title:
SELECT DISTINCT ON (hbg.group_id)
hbg.group_id,
hbg.id AS id,
hbg.group_name,
hbg.group_description,
hbg.group_type_id,
hbgt.group_type_name,
hbg.category_id,
hbg.effective_start_datetime,
hbg.created_by,
hbg.created_datetime,
hbg.archived_by,
hbg.archived_datetime
FROM hms_bbr_group hbg
LEFT JOIN hms_bbr_group_type hbgt
ON hbg.group_type_id = hbgt.group_type_id
ORDER BY
hbg.group_id,
hbg.id DESC;
test in pgAdmin: (only selecting distinct id)
I am trying to translate this inside a function in my Laravel Controller
Function:
public function fetchgroup(){
$all_groups = HmsBbrGroup::join('hms_bbr_group_type', 'hms_bbr_group.group_type_id', '=', 'hms_bbr_group_type.group_type_id')
->distinct('group_id')
->orderBy('group_id', 'ASC', 'id', 'DESC')->get();
return response()->json([
'all_groups'=>$all_groups,
]);
}
The code above works differently though, the screenshot below is the output. The rows shown are different:
I tried changing up the orderBy but the rows shown are still not the correct id (the highest value id on every group_id)
any help would be appreciated thanks
UPDATE:
tried tweaking the function abit but the output is exactly the same as the screenshot:
$all_groups = HmsBbrGroup::leftJoin('hms_bbr_group_type', 'hms_bbr_group.group_type_id', '=', 'hms_bbr_group_type.group_type_id')
->distinct('hms_bbr_group.group_id')
->orderBy('group_id', 'ASC', 'id', 'DESC')->get();
UPDATE 2
I tried changing up the distinct in the function but the code below does not work as intended as well
$all_groups = HmsBbrGroup::join('hms_bbr_group_type', 'hms_bbr_group.group_type_id', '=', 'hms_bbr_group_type.group_type_id')
->selectRaw('DISTINCT ON (group_id),
hms_bbr_group.group_id,
hms_bbr_group.id AS id,
hms_bbr_group.group_name,
hms_bbr_group.group_description,
hms_bbr_group.group_type_id,
hms_bbr_group_type.group_type_name,
hms_bbr_group.category_id,
hms_bbr_group.effective_start_datetime,
hms_bbr_group.created_by,
hms_bbr_group.created_datetime,
hms_bbr_group.archived_by,
hms_bbr_group.archived_datetime')
->orderBy('group_id', 'ASC', 'id', 'DESC')->get();

Related

How to use DISTINCT ON in Laravel Eloquent

Here is my full SQL Statement:
SELECT DISTINCT ON (hbg.group_id)
hbg.group_id,
hbg.id AS id,
hbg.group_name,
hbg.group_description,
hbg.group_type_id,
hbgt.group_type_name,
hbg.category_id,
hbg.effective_start_datetime,
hbg.created_by,
hbg.created_datetime,
hbg.archived_by,
hbg.archived_datetime
FROM hms_bbr_group hbg
LEFT JOIN hms_bbr_group_type hbgt
ON hbg.group_type_id = hbgt.group_type_id
ORDER BY
hbg.group_id,
hbg.id DESC;
I am trying to turn this statement into Laravel Eloquent code:
public function fetchgroup(){
$all_groups = HmsBbrGroup::leftJoin('hms_bbr_group_type', 'hms_bbr_group.group_type_id', '=', 'hms_bbr_group_type.group_type_id')
->distinct('group_id')
->orderBy('group_id', 'ASC', 'id', 'DESC')->get();
return response()->json([
'all_groups'=>$all_groups,
]);
}
I have read that eloquent somehow does not support DISTINCT ON so I cannot just simply do distinctOn('group_id')
If this is the case, is there any way to modify the select inside the function to use DISTINCT ON?
Use DB::raw inside your select statement or add a selectRaw at the end. Here are some options:
->select(
DB::raw('distinct on (hbg.group_id)'),
'hbg.group_id',
...)
->select(...)
->selectRaw('distinct on (hbg.group_id)')
->selectRaw('DISTINCT ON (hbg.group_id)
hbg.group_id,
hbg.id AS id,
hbg.group_name,
hbg.group_description,
hbg.group_type_id,
hbgt.group_type_name,
hbg.category_id,
hbg.effective_start_datetime,
hbg.created_by,
hbg.created_datetime,
hbg.archived_by,
hbg.archived_datetime
')

How to Query if Multiple Columns Reference to the Same Table

I am facing an issue here. I have a table called application and it will record who requests the application, who approves it, and who rejects it. The issue is the Requestor_id, Approver_id and Rejector_id are references to the same table. How can I query for the requestor_name, approver_name, and rejector_name in Laravel
Application table
Requestor_id ( reference to user id)
Application_Status
Module_id
Approver_id ( reference to user id)
Rejector_id ( reference to user id)
created_at
updated_at
Below is what I have tried but it can only retrieve for the requestor name
$Approval_Logs = DB::table('application')
->select('application.id','application.Application_Status', 'users.name','application.Approver_id','application.Rejector_id', 'ems_application.Request_Category','application.updated_at')
->join('ems_application', 'ems_application.Application_id', '=', 'application.id')
->join('users', 'users.id', '=', 'application.requestor_id')
->whereIn('application.Application_Status',['approved','rejected'])
->get()
->toArray();
I hope I can receive some hints from you. Thanks in advance!
You may use aliases in your joins also.
$Approval_Logs = DB::table('application')
->select(
'application.id',
'application.Application_Status',
'application.Approver_id',
'approver.name as approver_name',
'application.requestor_id',
'requestor.name as requestor_name',
'application.Rejector_id',
'rejector.name as rejector_name',
'ems_application.Request_Category',
'application.updated_at'
)
->join('ems_application', 'ems_application.Application_id', '=', 'application.id')
->join('users as requestor', 'requestor.id', '=', 'application.requestor_id')
->join('users as approver', 'approver.id', '=', 'application.approver_id')
->join('users as rejector', 'rejector.id', '=', 'application.rejector_id')
->whereIn('application.Application_Status',['approved','rejected'])
->get()
->toArray();
I am not completely familiar with your application, however you may want to utilize left_join instead of join for the approver and rejector joins in the event that there was not an approver or rejector.
If you would like to do it the "Laravel" way. I would create a model called Application and create relations
class Application extends Model {
public function requestor(){
return $this->belongsTo(Users::class, 'requestor_id');
}
public function approver(){
return $this->belongsTo(Users::class, 'approver_id');
}
public function rejector(){
return $this->belongsTo(Users::class, 'rejector_id');
}
}
Then in your controller, you can run the following query:
$application = Application::whereHas('requestor', function($query) {
$query->where('first_name', 'John');
})->whereHas('approver', function($query) {
$query->where('first_name', 'Peter');
})->whereHas('rejector', function($query) {
$query->where('first_name', 'Michael');
})->get();
That should query the users table for the first names. I don't know how efficient this will be, but give it a try;

Eloquent advanced where within an advanced join

I'm trying to do the following join:
Schedules::select()
->leftJoin('histories', function ($j)
{
$j->on('histories.schedule_id', '=', 'schedules.id')
->where('histories.test', '=', DB::raw('schedules.test'))
->where(function ($q)
{
$q->where('histories.order_id', '=', 'schedules.order_id')
->orWhere('histories.customer_id', '=', DB::raw('schedules.customer_id'));
});
});
When I do, Laravel reports the error:
Missing argument 2 for Illuminate\Database\Query\JoinClause::where()
How do I structure this query in Eloquent syntax so that I get the equivalent of the following for the join statement?
left join histories
on histories.schedule_id = schedules.id
and histories.test = schedules.test
and (
histories.order_id = schedules.order_id
or histories.customer_id = schedules.customer_id
)
Unfortunately JoinClauses where doesn't work like ordinary where clause, and you can't pass closure for nested wheres, so you just need to repeat part of your conditions.
Also, you don't need where and DB::raw for your additional join clauses, instead use on once again.
So basically you need this:
$j->on('histories.schedule_id', '=', 'schedules.id')
->on('histories.test', '=', 'schedules.test')
->on('histories.order_id', '=', 'schedules.order_id')
->orOn('histories.schedule_id', '=', 'schedules.id')
->on('histories.test', '=', 'schedules.test')
->on('histories.customer_id', '=', 'schedules.customer_id');

Multi join select query on Laravel

How to write this query in Laravel. I am new in laravel.
Example:
SELECT * FROM ((respassanger join ((`reservation` join flightres
on flightres.res_id = reservation.id)) on respassanger.res_id = reservation.id)
join passanger on respassanger.pas_id = passanger.pas_id)
Have you read the documentation? Checkout Laravel's query builder. Using your table names as mentioned, work from the following example in the docs for your needs:
DB::table('users')
->join('contacts', function($join)
{
$join->on('users.id', '=', 'contacts.user_id')->orOn(...);
})
->get();
So something like:
DB::table('respassanger')
->join('reservation', function($join)
{
$join->on('flightres.res_id', '=', 'reservation.id')
})
->join('passanger', 'respassanger.pas_id', '=', 'passanger.pas_id')
->select( ... )
->get();
Not sure how correct the above is, but tweak it if it doesn't work.

Select sql code in Laravel

Following query returning six values
SELECT tbl_start FROM timetable inner join route ON tbl_rte_id = id WHERE rte_origin = "UL" and rte_destination = "HW" ORDER BY(tbl_start) DESC;
And my laravel code is returning only one value
$tables = Timetable::join('route', 'tbl_rte_id', '=', 'id')
->where('rte_origin', $origin, 'AND')
->where('rte_destination', $destination)
->orderBy('tbl_start', 'desc')
->get();
foreach ($tables as $table) {
$result[$table->id] = $table->tbl_start;
}
This laravel code is not similar or similar. Can anyone help me.
Change this part:
->where('rte_origin', $origin, 'AND')
// to:
->where('rte_origin', $origin)
It will know by default that it's AND operator
And if you want to provide this operator, then do this:
->where('rte_origin', '=', $origin, 'AND')
You may try something like this:
$tables = Timetable::join('route', 'tbl_rte_id', '=', 'timetable.id')
->where('rte_origin', $origin)
->where('rte_destination', $destination)
->orderBy('tbl_start', 'desc')
->get()->lists('tbl_start', 'id');
The $tables will contain an array of id => tbl_start pairs.
Add a listener in your routes.php
Event::listen('illuminate.query', function($sql){
var_dump($sql);
});
Then execute both queries and check if you have the same result