How to use alias in where clause laravel elequent with postgres - laravel

This is my query
Student::query()
->addSelect(['presentCount' =>
Score::query()
->selectRaw('count(*)')
->whereColumn('student_id', '=', 'students.id')
->where('created_at', '>', getBeginningOfThisYear())
->where('presence', '=', 1)
])->where('presentCount', '>=', 5)->get()
the raw SQL is
select "students".*, (select count(*) from "scores" where "student_id" = "students"."id" and "created_at" > ? and "presence" = ? and "scores"."deleted_at" is null) as "presentCount" from "students" where "presentCount" >= ? and "students"."deleted_at" is null
the problem is presentCount is an alias and it can not be used in where clause, however if I can change the SQL to be like:
select * from (select "students".*, (select count(*) from "scores" where "student_id" = "students"."id" and "created_at" > ? and "presence" = ? and "scores"."deleted_at" is null) as "presentCount" from "students" ) as students where "students"."presentCount" >= ? and "students"."deleted_at" is null
The question is how can I transform the query using query builder not raw SQL?

I found a solution:
Student::query()->from(fn($q) => $q->from('students')->addSelect(['presentCount' =>
Score::query()
->selectRaw('count(*)')
->whereColumn('student_id', '=', 'students.id')
->where('created_at', '>', getBeginningOfThisYear())
->where('presence', '=', 1)
]), 'students')->where('presentCount', '>', 5)->get()
will generate:
select * from (select "students".*, (select count(*) from "scores" where "student_id" = "students"."id" and "created_at" > ? and "presence" = ? and "scores"."deleted_at" is null) as "presentCount" from "students") as "students" where "presentCount" > ? and "students"."deleted_at" is null
and it works correctly.

Related

Laravel nested or with and in where condition

My Expected query is
select count(*) as aggregate from `books`
where (`books`.`is_deleted` = 0)
and `category_id` = '61'
and (`title` like '%問いかけの作法 チームの魅力と才能を引き出す技術%' or `title` like '%問イカケノ作法 チームノ魅力ト才能ヲ引キ出ス技術%' or `title` like '%問いかけの作法 ちーむの魅力と才能を引き出す技術%');
I have written my conditions like below ways
$queryCondition = $this::where(['books.is_deleted' => false]);
if( isset($queryString['category']) ){
$queryCondition->where('category_id',$queryString['category']);
}
if( isset($queryString['searchKey']) ){
$search = mb_convert_kana($queryString['searchKey'],"rns");
$kana = mb_convert_kana($search,"KVC");
$katakana = mb_convert_kana($search,"KVc");
$queryCondition->where('title','like','%'.$search.'%')
->orWhere('title','like','%'.$kana.'%')
->orWhere('title','like','%'.$katakana.'%')
;
}
I'm getting the output query like below
select count(*) as aggregate from `books`
where (`books`.`is_deleted` = 0)
and `category_id` = '61'
and `title` like '%問いかけの作法 チームの魅力と才能を引き出す技術%' or `title` like '%問イカケノ作法 チームノ魅力ト才能ヲ引キ出ス技術%' or `title` like '%問いかけの作法 ちーむの魅力と才能を引き出す技術%';
Without the () in last condition. How can I fix it ? Without this way has there any other ways to implement nested or in laravel ? Example
$query->where([
'OR' => [
[name LIKE' => '%'.$search.'%'],
[search LIKE' => '%'.$kana.'%'],
[search LIKE' => '%'.$katakana.'%']
]
]);
try this
->where(function ($query) {
$query->where('title','like','%問いかけの作法 チームの魅力と才能を引き出す技術%')
->orWhere('title','like','%問イカケノ作法 チームノ魅力ト才能ヲ引キ出ス技術%')
->orWhere('title','like','%問いかけの作法 ちーむの魅力と才能を引き出す技術%');
})
->get();
The closure will give you the () that you are seeking for.
Laravel documentation 9.x itself asks to add orwhere via above.
You should always group orWhere calls in order to avoid unexpected behavior when global scopes are applied.
From docs:
$users = DB::table('users')
->where('votes', '>', 100)
->orWhere(function($query) {
$query->where('name', 'Abigail')
->where('votes', '>', 50);
})
->get();
which will give you,
select * from users where votes > 100 or (name = 'Abigail' and votes > 50)
You should try whereRaw with raw query instead of orWhere
So, instead of this
->orWhere('title','like','%'.$kana.'%')
->orWhere('title','like','%'.$katakana.'%');
Do this
->whereRaw('title LIKE "%$kana%" OR title LIKE "%$katakana%" ');
From my experience, anytime i use orWhere(), it ignores all other conditions so i prefer to use whereRaw and it works fine for me without any issues

how to convert below SQL query in Laravel query?

how to convert below sql query in laravel
SELECT `models`.* FROM (
(SELECT * FROM `models` WHERE `models`.`fk_car_model_id` = 3 LIMIT 5)
UNION ALL
(SELECT * FROM `models` WHERE `models`.`fk_car_model_id` = 2 LIMIT 3)
UNION ALL
(SELECT * FROM `models` WHERE `models`.`fk_car_model_id` = 1 LIMIT 2)
) AS `models`
// if you want to get all the fields, you can use the following:
$fields = '*';
// if you want to select only some fields, use this:
// $fields = [
// 'id',
// 'fk_car_model_id',
// ];
$data = Model::select($fields)
->where('fk_car_model_id', 3)->limit(5)
->unionAll(
Model::select($fields)
->where('fk_car_model_id', 2)->limit(3)
)
->unionAll(
Model::select($fields)
->where('fk_car_model_id', 1)->limit(2)
)
->get()
->toArray();
return $data;
Or you can use something like this:
$query = DB::table('models')
->select('models.*')
->where('models.fk_car_model_id', '=', 3)
->limit(5)
->unionAll(
DB::table('models')
->select('models.*')
->where('models.fk_car_model_id', '=', 2)
->limit(3)
)
->unionAll(
DB::table('models')
->select('models.*')
->where('models.fk_car_model_id', '=', 1)
->limit(2)
)
->get();
Please check it, this might help you. This might not b exact as you want but you can get some idea about its working and change as per you requirements.
Model::where(function ($query) {
$query->where('fk_car_model_id', '=', 3)
->limit(5)
})->orWhere(function ($query) {
$query->where('fk_car_model_id', '=', 2)
->limit(3)
})->orWhere(function ($query) {
$query->where('fk_car_model_id', '=', 1)
->limit(2)
})->get();
See more for Documentation for reference Logical Grouping

Laravel Eloquent Subquery with condition

How to add a subquery to the main query with a condition? The result of the request should be similar to this:
select
`tasks`.*,
`users`.`name` as `user_name`,
(select count(*) from tasks_favorites on tasks_favorites.task_id = tasks.id and tasks_favorites.user_id = 38) as `is_favorite`
from `tasks`
left join `users` on `users`.`id` = `tasks`.`user_id`
where
`tasks`.`id` = 149
I try this query but I get an error:
$task = DB::table('tasks')
->select(
'tasks.*',
'users.name as user_name',
)
->when(Auth::check(), function($query) {
return $query->addSelect(
DB::table('tasks_favorites')->where('tasks_favorites.task_id', 'tasks.id')->where('tasks_favorites.user_id', auth()->user()->id)->count()
) ;
})
->leftJoin('users', 'users.id', 'tasks.user_id')
->where('tasks.id', $task_id)
->get()
->first() ;
did you try the selectRaw or raw method?
something like this
$task = DB::table('tasks')
->select(
'tasks.*',
'users.name as user_name',
)
->when(Auth::check(), function($query) {
return $query->addSelect(
DB::raw('select count(id) from tasks_favorites where tasks_favorites.task_id=tasks.id AND tasks_favorites.user_id='.auth()->user()->id.' as mycount')
);
})
->leftJoin('users', 'users.id', 'tasks.user_id')
->where('tasks.id', $task_id)
->get()
->first() ;

Laravel 5.6 Or Query Multiple in where

This is my filter query function
$keywords = [];
foreach($columns as $key => $value){
$keywords[] = [$key, 'LIKE', '%'.$value.'%'];
}
$query= $this->model ->orderBy('name', 'asc')->where('is_deleted', 0)->Where($keywords);
if($status=="yes")
$query= $query->where('status',1);
$query= $query->get();
return $query;
For the above function, i got the following query
select * from stores where is_deleted = 0 and status = 1 AND (name LIKE %r% AND address LIKE %r%) order by name asc
But i need Or instead of ANd in the like query
select * from `stores` where `is_deleted` = 0 and `status` = 1 AND (`name` LIKE %r% or `address` LIKE %r%) order by `name` asc
Please tell in which place i need to change?
You can use Where and orWhere.
$query= $this->model->orderBy('name', 'asc')->where('is_deleted', 0)->
orWhere($key, 'LIKE', '%'.$value.'%');
You have to group those orWhere() queries in one where() clause
$query = $this->model->where([
['is_deleted' => 0],
['status' => $status]
])
->where(function ($query) use($columns) {
foreach($columns as $key => $value) {
$query->orWehre($key, 'like', "%$value%");
}
})
->orderBy('name');

Laravel Query Builder error with joins and parameter grouping

Have a set of queries I would like to convert from raw to query builder but having issues when using parameter grouping:
SQLSTATE[42S22]: Column not found: 1054 Unknown column
'users.trail_ends_at' in 'where clause' (SQL: select 'campaigns'.*
from 'users' inner join 'campaigns` on 'users'.'id' =
'campaigns'.'user_id' inner join 'subscriptions' on 'users'.'id' =
'subscriptions'.'user_id' where ('users'.'trial_ends_at >= 2018-06-15
00:00:00 or 'users'.'trail_ends_at' is null) and 'campaign'.'active' =
1 and 'campaign'.'style' = monthly and
('subscriptions'.'trial_ends_at' >= 2018-06-15 00:00:00 or
'subscriptions'.'trail_ends_at' is null) and
('subscriptions'.'ends_at' >= 2018-06-15 00:00:00 or
'subscriptions'.'ends_at' is null))
SQL query that works:
DB::select('select c.*
FROM users u, subscriptions s, campaigns c
WHERE c.user_id = u.id
AND s.user_id = u.id
AND (u.trial_ends_at IS NULL OR u.trial_ends_at >= CURDATE() + :leadDays1)
AND c.active > 0
AND c.style = \'monthly\'
AND (s.ends_at IS NULL OR s.ends_at >= CURDATE() + :leadDays2)
AND (s.trial_ends_at IS NULL OR s.trial_ends_at >= CURDATE() + :leadDays3)
AND c.send_on <= CURDATE() + :leadDays4
AND MONTH(c.send_on) = MONTH(CURDATE() + :leadDays5),
AND DAYOFMONTH(c.send_on) = DAYOFMONTH(CURDATE() + :leadDays6)',
[
'leadDays1' => $leadDays,
'leadDays2' => $leadDays,
'leadDays3' => $leadDays,
'leadDays4' => $leadDays,
'leadDays5' => $leadDays,
'leadDays6' => $leadDays
]
);
Builder query that errors:
$checkDate = Carbon::today()->addDays($leadDays);
return $campaigns = DB::table('users')
->join('campaigns', 'users.id', '=', 'campaigns.user_id')
->join('subscriptions', 'users.id', '=', 'subscriptions.user_id')
->select('campaigns.*')
->where(function ($query) use ($checkDate) {
return $query->where('users.trial_ends_at', '>=', $checkDate)
->orWhereNull('users.trail_ends_at');
})
->where('campaign.active', '=', 1)
->where( 'campaign.style', '=', $style)
->where(function ($query) use ($checkDate)
{
return $query->where('subscriptions.trial_ends_at', '>=', $checkDate)
->orWhereNull('subscriptions.trail_ends_at');
})
->where(function ($query) use ($checkDate) {
return $query->where('subscriptions.ends_at', '>=', $checkDate)
->orWhereNull('subscriptions.ends_at');
});
Check your column names. I think trail_ends_at should be trial_ends_at.

Resources