How to convert raw SQL query to Laravel Query Builder - php

I need a following code to convert to Laravel query can any one help me with these.
SELECT id, `leave_name`, `total_leave_days`, leave_id, leave_taken_days FROM `leaves` AS t1 INNER JOIN ( SELECT leave_id, SUM(`leave_taken_days`) AS leave_taken_days FROM `leave_applications` WHERE user_id = 2 AND statuses_id = 2 GROUP BY leave_id ) AS t2 ON t1.id = t2.leave_id
I even tried but the output is not showing atall.
$user_leaves = DB::table('leaves')
->select('id', 'leave_name', 'total_leave_days', 'leave_id', 'leave_taken_days')
->join('leave_application', 'leave_application.leave_id', '=', 'leave.id')
->select('leave_application.leave_id', DB::raw("SUM(leave_taken_days) as leave_application.leave_taken_days"))
->where('user_id','=', 2)
->where('statuses_id','=', 2)
->get();
How can I solve this issue?
UPDATE
Relations between two models.
Leave Model
public function leave_application()
{
return $this->belongsTo(LeaveApplication::class, 'id' , 'leave_id');
}
Leave Application Model
public function leave()
{
return $this->belongsTo(Leave::class, 'leave_id', 'id');
}

Try this :
$user_leaves = Leave::select('leaves.id', 'leaves.leave_name', 'leaves.total_leave_days', 'leave_applications.leave_id', DB::raw('SUM(leave_applications.leave_taken_days) as leave_taken_days'))
->with('leave_application')
->whereHas('leave_application', function($q) {
$q->where('user_id', 2)
->where('statuses_id', 2);
})
->groupBy('leaves.id')
->get();

On this topic I would like to give my recommendations for some tools to help you out in the future.
SQL Statement to Laravel Eloquent to convert SQL to Laravel query builder. This does a decent job at low level queries. It also saves time when converting old code.
The other tool I use to view the query that is being run is Clock Work
I keep this open in a tab and monitor slow nasty queries or, also gives me perspective on how the query builder is writing SQL. If you have not use this extension I highly recommend getting and using it.

Actually I found my answer,
$user_leaves = DB::table('leaves as t1')
->select('t1.id', 't1.leave_name', 't1.total_leave_days', 't2.leave_id', 't2.leave_taken_days')
->join(DB::raw('(SELECT leave_id, SUM(leave_taken_days) AS leave_taken_days FROM leave_applications WHERE user_id = ' . $user_id . ' AND statuses_id = 2 GROUP BY leave_id) AS t2'), function ($join) {
$join->on('t1.id', '=', 't2.leave_id');
})
->get();

You can use DB:select("your query", params) and put your query and params (as an array (optional)
As below sample:
$result = DB:select("
SELECT id, `leave_name`, `total_leave_days`, leave_id, leave_taken_days
FROM `leaves` AS t1
INNER JOIN (
SELECT leave_id, SUM(`leave_taken_days`) AS leave_taken_days
FROM `leave_applications`
WHERE user_id = 2
AND statuses_id = 2
GROUP BY leave_id
) AS t2 ON t1.id = t2.leave_id" , $params
);
return response()->json($result);

Related

laravel elequent builder join with paginate

i have this query to return data from two tables based on DISTINCT destination_tbls.destination
like the following:
SELECT DISTINCT
destination_tbls.destination,
MIN(sms_details.id),
MIN(sms_details.msg_timestamp) AS TIMESTAMP,
MIN(destination_tbls.count)
FROM
sms_details
JOIN
(
SELECT
*
FROM
destination_tbls
)
destination_tbls
ON destination_tbls.id = sms_details.destination_tbls_id
GROUP BY
destination_tbls.destination;
Now how to use the paginate with them,
I tried something like this but don't work:
DB::select('
SELECT DISTINCT destination_tbls.destination,MIN(sms_details.id),MIN(sms_details.msg_timestamp) AS TIMESTAMP,MIN(destination_tbls.count)
FROM sms_details
JOIN(SELECT * FROM destination_tbls) destination_tbls ON destination_tbls.id=sms_details.destination_tbls_id
GROUP BY destination_tbls.destination
')->simplePaginate(100);
Any help would be appreciated!
If you want to use laravel's pagination, you need to write the query using the query builder methods.
$results = DB::table('sms_details')
->select('destination_tbls.destination')
->selectRaw('min(sms_details.id)')
->selectRaw('min(sms_details.msg_timestamp) as timestamp')
->selectRaw('min(destination_tbls.count)')
->distinct()
->joinSub(
function ($sub) {
$sub->from('destination_tbls');
},
'destination_tbls',
function ($join) {
$join->on('destination_tbls.id', '=', 'sms_details.destination_tbls_id');
}
)
->groupBy('destination_tbls.destination')
->simplePaginate(100);
Since you're not really doing anything in the subquery join, you could join the table instead.
$query = DB::table('sms_details')
->select('destination_tbls.destination')
->selectRaw('min(sms_details.id)')
->selectRaw('min(sms_details.msg_timestamp) as timestamp')
->selectRaw('min(destination_tbls.count)')
->distinct()
->join('destination_tbls', 'destination_tbls.id', '=', 'sms_details.destination_tbls_id')
->groupBy('destination_tbls.destination')
->simplePaginate(100);

Laravel query builder join after where clause

I am using laravel 8. I have this mysql command which I want to convert into laravel query builder style:
select allocation.*, leav_leave_types.leave_type_code
from (
select * from leav_employee_annual_leave_allocations
where leave_year_id = $year_id and employee_id = $user_id
) as allocation
left join leav_leave_types on (leav_leave_types.id = allocation.leave_type_id)
Actually I want to apply a where clause first and then perform a left join for better performance.
How can I convert it into query builder style?
The only thing from your query that is not currently in the documentation is using a subquery as the main table.
This can be done by passing either a Closure or a Builder instance to the table() or from() method.
DB::table(closure, alias)
DB::table(builder, alias)
DB::query()->from(closure, alias)
DB::query()->from(builder, alias)
Using a Closure:
DB::table(function ($sub) use ($user_id, $year_id) {
$sub->from('leav_employee_annual_leave_allocations')
->where('leave_year', $year_id)
->where('employee_id', $user_id);
}, 'allocation')
->select('allocation.*', 'leav_leave_types.leave_type_code')
->leftJoin('leav_leave_types', 'leav_leave_types.id', 'allocation.leave_type_id')
->get();
DB::query()
->select('allocation.*', 'leav_leave_types.leave_type_code')
->from(function ($sub) use ($user_id, $year_id) {
$sub->from('leav_employee_annual_leave_allocations')
->where('leave_year', $year_id)
->where('employee_id', $user_id);
}, 'allocation')
->leftJoin('leav_leave_types', 'leav_leave_types.id', 'allocation.leave_type_id')
->get();
Using a Builder instance
$sub = DB::table('leav_employee_annual_leave_allocations') // or DB::query()->from('leav_employee_annual_leave_allocations')
->where('leave_year', $year_id)
->where('employee_id', $user_id);
DB::table($sub, 'allocation')
->select('allocation.*', 'leav_leave_types.leave_type_code')
->leftJoin('leav_leave_types', 'leav_leave_types.id', 'allocation.leave_type_id')
->get();
// personally my favorite way. I find it very readable.
$sub = DB::table('leav_employee_annual_leave_allocations') // or DB::query()->from('leav_employee_annual_leave_allocations')
->where('leave_year', $year_id)
->where('employee_id', $user_id);
DB::query()
->select('allocation.*', 'leav_leave_types.leave_type_code')
->from($sub, 'allocation')
->leftJoin('leav_leave_types', 'leav_leave_types.id', 'allocation.leave_type_id')
->get();
The generated SQL looks like this
select "allocation".*, "leav_leave_types"."leave_type_code" from (
select * from "leav_employee_annual_leave_allocations"
where "leave_year" = ? and "employee_id" = ?
) as "allocation"
left join "leav_leave_types" on "leav_leave_types"."id" = "allocation"."leave_type_id"
If you want a parenthesis around your join condition to be generated, you should use one of the following notations instead.
leftJoin('leav_leave_types', ['leav_leave_types.id' => 'allocation.leave_type_id'])
leftJoin('leav_leave_types', function ($join) {
$join->on(['leav_leave_types.id' => 'allocation.leave_type_id']);
})
leftJoin('leav_leave_types', function ($join) {
// will generate a parenthesis if there's more than one condition
$join->on('leav_leave_types.id', 'allocation.leave_type_id')
->on(...) // and condition
->orOn(...); // or condition
})
Alternatively, you could turn the SQL around to
select *,
( SELECT leave_type_code
FROM leav_leave_types
WHERE id = allocation.leave_type_id
) AS leave_type_code
FROM leav_employee_annual_leave_allocations AS allocation
where leave_year_id = $year_id and employee_id = $user_id
(This might be more efficient.)
In either case leav_employee_annual_leave_allocations would benefit from INDEX(employee_id, leave_year_id).

I'm new to Laravel and I wanted to convert the SQL query to laravel [duplicate]

I want to get all the records from a table which do not exist in other table in Laravel 5.1.
I know how to do this in core php, and it works fine with the following code
SELECT t1.name
FROM table1 t1
LEFT JOIN table2 t2 ON t2.name = t1.name
WHERE t2.name IS NULL
the model
public function audiences()
{
return $this->belongsTo('App\BridalRequest', 'request_id');
}
but when i try to do the same in Laravel by using the following code,
$all_bridal_requests_check = \DB::table('bridal_requests')
->where(function($query)
{
$query->where('publisher', '=', 'bq-quotes.sb.com')
->orWhere('publisher', '=', 'bq-wd.com-bsf');
})
->whereNotIn('id', function($query) { $query->table('audiences')->select('request_id'); })
->orderBy('created_on', 'desc')
->get();
then it gives me this error
Call to undefined method Illuminate\Database\Query\Builder::table()
The above mentioned query can be built using laravel query builder in the following manner.
SELECT t1.name
FROM table1 t1
LEFT JOIN table2 t2 ON t2.name = t1.name
WHERE t2.name IS NULL
This is equivalent to below query built using Laravel's query builder.
\DB::table('table1 AS t1')
->select('t1.name')
->leftJoin('table2 AS t2','t2.name','=','t1.name')
->whereNull('t2.name')->get();
Late but yes I would like to add into this question. Create laravel eloquent relationship between table by writing below code in users model file,
public function mu_user()
{
return $this->hasMany(\App\MainUser::class, 'id');
}
Now get all records from users table which does not have main user in relation as below,
$users = Users::doesnthave('mu_user')->get();
If you want to get users who have main_users then you can write query as below,
$users = Author::has('mu_user')->get();
It's such easy. Hope it helps!

i want this query in laravel

I want to know how to write an exact query in laravel using joins, please help somebody to solve this issue
select tickets.* from `employees` inner join `tickets` on
`employees`.`user_id` = `tickets`.`emp_id` inner join `categories` on
`categories`.`acc_id` = `employees`.`acc_id` and `categories`.`id` =
(`tickets`.`cat_id` or `tickets`.`cat_id`=0) where (`employees`.`user_id` = 11)
If you are using plain query builder,
$result = DB::select(DB::raw("tickets.*"))
->join("tickets","employees.user_id","=","tickets.emp_id")
->join('categories', function ($join) {
$join->on("categories.acc_id","=","employees.acc_id");
$join->on("categories.id","=",DB::raw("(tickets.cat_id or tickets.cat_id=0)")
})->where("employees.user_id",11)->get();
Since the Answer by #Drakula Predator is good
But I avoided using the Raw queries
$laravelWay = DB::table('employees')
->select('tickets.*')
->join('tickets','employees.user_id','=','tickets.emp_id')
->join('categories', function ($join) {
$join->on('categories.acc_id','=','employees.acc_id')
->on('categories.id','=','tickets.cat_id')
->orOn('tickets.cat_id','=','0');
})
->where('employees.user_id','=',11);

SQL exists in Laravel 5 query builder

Good morning,
I've been trying for quite a lot of time to translate this query(which returns an array of stdClass) into query builder so I could get objects back as Eloquent models.
This is how the query looks like untranslated:
$anketa = DB::select( DB::raw("SELECT *
FROM v_anketa a
WHERE not exists (select 1 from user_poeni where anketa_id=a.id and user_id = :lv_id_user)
Order by redni_broj limit 1"
), array( 'lv_id_user' => $id_user,
));
I have tried this, but it gives a syntax error near the inner from in the subquery:
$anketa = V_anketa::selectRaw("WHERE not exists (select 1 from user_poeni where anketa_id=a.id and user_id = :lv_id_user)", array('lv_id_user' => $id_user,)
)->orderBy('redni_broj')->take(1)->first();
The problem is this exists and a subquery in it. I couldn't find anything regarding this special case.
Assume each table has an appropriate Eloquent model.
V_anketa is a view. The db is postgresql.
As far as the query goes I believe this should work:
$anketa = V_anketa::whereNotExists(function ($query) use ($id_user) {
$query->select(DB::raw(1))
->from('user_poeni')
->where('anketa.id', '=', 'a.id')
->where('user_id', '=', $id_user);
})
->orderBy('redni_broj')
->first();
but I'm not clear on what do you mean by "assuming every table has an Eloquent model" and "V_anketa" is a view...
Assuming the SQL query is correct, this should work:
$anketa = DB::select(sprintf('SELECT * FROM v_anketa a WHERE NOT EXISTS (SELECT 1 FROM user_poeni WHERE anketa_id = a.id AND user_id = %s) ORDER BY redni_broj LIMIT 1', $id_user));
If you want to get back an Builder instance you need to specify the table:
$anketa = DB::table('')->select('');
If you however, want to get an Eloquent Model instance, for example to use relations, you need to use Eloquent.

Categories