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.
Related
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
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() ;
I have two tables, Shows and Episodes, each episode has show_id linking them one to many.
Now I need to get latest 6 episodes, one per show, where show.active is true
I've tried the following code:
$episodes = Episode::select(DB::raw('t.*'))
->from(DB::raw('(SELECT * FROM episodes ORDER BY id DESC) t'))
->whereHas('show', function($query) {
$query->where('active', '=', true);
})
->groupBy('t.show_id')
->take(6)
->get();
Unfortunately, I get the following:
Column not found: 1054 Unknown column 'episodes.show_id' in 'where clause' (SQL: select t.* from (SELECT * FROM episodes ORDER BY id DESC) t where exists (select * from shows where episodes.show_id = shows.id and active = 1) group by t.show_id limit 6)
I've also tried:
$episodes = Episode::where('active', true)
->orderBy('id', 'DESC')
->whereHas('show', function($query) {
$query->where('active', '=', true);
})
->groupBy('show_id')
->take(6)
->get();
It shows no error, but doesn't return latest of each show, groupBy gets the first record, I need the latest
This should work:
$episodes = Episode::where('active', true)
->whereHas('show', function($query) {
$query->where('active', '=', true);
})
->groupBy('show_id')
->orderBy('id', 'DESC')
->take(6)
->get();
You can try this
$episodes = Episode::selectRaw('max(id) as id, show_id')
->whereHas('show', function($query) {
$query->where('active', '=', true);
})
->orderBy('id', 'DESC')
->groupBy('show_id')
->take(6)
->get();
You can use a WHERE IN subquery:
$ids = Episode::selectRaw('max(id)')
->whereHas('show', function ($query) {
$query->where('active', '=', true);
})->groupBy('show_id');
$episodes = Episode::whereIn('id', $ids)
->take(6)
->get();
SELECT user_sessions.os, COUNT(*) FROM user_sessions
JOIN (SELECT MIN(created_at) AS MinCreatedAt, user_id FROM user_sessions
GROUP BY user_id) AS us2
ON (user_sessions.created_at = us2.MinCreatedAt
AND user_sessions.user_id = us2.user_id
GROUP BY user_sessions.os
This is a raw SQL query which I tried to convert in Eloquent but failed. My trial code is...
$q1 = self::select(DB::raw('MIN(created_at) as MinCreatedAt, user_id'))->groupBy('user_id');
$q2 = self::select(DB::raw('user_sessions.os, count(*)'));
$users = self::
select($q2)->joinSub($q1, 'us2', function ($join) {
$join->on('user_sessions.created_at = us2.MinCreatedAt AND user_sessions.user_id = us2.user_id ');
})->get();
Error
stripos() expects parameter 1 to be string object given
try this one.
$joinQuery = "(".DB::table('user_sessions')
->selectRaw('MIN(created_at) AS MinCreatedAt, user_id')
->groupBy('user_id')->toSql().") as us2" ;
$users = DB::table('user_sessions')
->selectRaw("user_sessions.os, COUNT(*)")
->join(DB::raw($joinQuery), function ($join) {
$join->on('user_sessions.created_at', '=', 'us2.MinCreatedAt')->on('user_sessions.user_id', '=', 'us2.user_id');
})
->groupBy('user_sessions.os');
Update
$q1 = self::select(DB::raw('MIN(created_at) as MinCreatedAt, user_id'))->groupBy('user_id');
$q2 = self::select(DB::raw('user_sessions.os, count(*)'));
$users = $q2->joinSub($q1, 'us2', function ($join) {
$join->on('user_sessions.created_at = us2.MinCreatedAt AND user_sessions.user_id = us2.user_id ');
})->groupBy('user_sessions.os')->get();
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');