I need to execute the following MySQL query using Laravel Eloquent ORM:
select * from `events`
where `app_id` = 1
and ((`startDate` < now() and endDate is null) or (`endDate` < now()))
order by `startDate` desc
My best try so far:
Event::where('app_id', '=', 1)
-> where(function ($query) {
$query -> where([['startDate', '<', Carbon::now() -> toDateTimeString()]) -> whereNull('endDate');
}) -> orWhere([['endDate', '<', Carbon::now() -> toDateTimeString()]])
-> orderBy('startDate', 'desc') -> get();
Which is not exactly what I want as it results in:
select * from `events`
where `app_id` = 1
and (`startDate` < now() and endDate is null) or (`endDate` < now())
order by `startDate` desc
(Missing extra parentheses in the second compound where condition).
Any idea? Thanks in advance.
This should do the task:
Event::where('app_id', '=', 1)
->where(function ($q) {
$q->where(function($query){
$query->where('startDate', '<', Carbon::now()->toDateTimeString())->whereNull('endDate');
})->orWhere('endDate', '<', Carbon::now()->toDateTimeString());
})
->orderBy('startDate', 'desc') -> get();
Related
I need to select all offers where the merchant has status open and dd_merchant set to 1. The match between merchant and offer is done using a col named mid.
In my offer model I have the following:
public function merchants()
{
return $this->belongsTo(Merchant::class,'mid','mid');
}
My query looks like this:
$data['offers']= Offer::whereRelation('merchants', 'status', 'Open')
->whereRelation('merchants', 'dd_merchant', '1')
->where('status', '=', 'Loaded')
->where("start", "<=", date("Y-m-d"))
->where("end", ">=", date("Y-m-d"))
->where('category', '=', $request->category)
->orderBy('title','ASC')
->paginate(20);
For the sake of this test, I have one merchant set to status 'Closed' and has dd_merchant set to 0 in the database.
The query returned by this is
select * from `offers` where (exists (select * from `merchants` where `offers`.`mid` = `merchants`.`mid` and `status` = 'Open' and `merchants`.`deleted_at` is null) and exists (select * from `merchants` where `offers`.`mid` = `merchants`.`mid` and `dd_merchant` = '1' and `merchants`.`deleted_at` is null) and `status` = 'Loaded' and `start` <= '2022-10-03' and `end` >= '2022-10-03' ) and `offers`.`deleted_at` is null order by `title` asc limit 20 offset 0
For some reason, I am still getting offers from that merchant with the above query. Am I assuming wrong that whereRelation() filters the offers based on the condition on the second table? If so, how can I achieve my goal?
In one of the 27 variants of this I tried so fare, I used the wherehas() like this:
$data['offers']= Offer::
whereHas('merchants', function (Builder $query) {
$query->where('dd_merchant', '=', '1')->where('status', '=', 'Open');
})
->where('status', '=', 'Loaded')
->where("start", "<=", date("Y-m-d"))
->where("end", ">=", date("Y-m-d"))
->where('category', '=', $request->category)
->orderBy('title','ASC')
->paginate(20);
The above made a lot more sense to me but I get the same result ... I get offers that should not be there.
I am using Laravel Framework 6.16.0.
I have the following sql query:
SELECT DISTINCT
`companies`.*
FROM
`companies`
LEFT JOIN `trx` ON `trx`.`companies_id` = `companies`.`id`
WHERE
`trx`.`transaction_date` >= 2020-11-12 AND companies.symbol NOT IN (SELECT DISTINCT
companies.symbol
FROM
`companies`
LEFT JOIN articles a ON a.companies_id = companies.id
WHERE
a.created_at >= 2020-11-12
ORDER BY
created_at
DESC)
ORDER BY
transaction_date
DESC
I have created the following eloquent query:
DB::connection('mysql_prod')->table('companies')->select('companies.symbol')
->leftJoin('trx', 'trx.companies_id', '=', 'companies.id')
->where('trx.transaction_date', '>=', Carbon::today()->subDays(1)->startOfDay())
->orderBy('transaction_date', 'desc')
->distinct()
->get('symbol');
However, I am not sure how to pack the in my eloquent query to get all the symbol back that should be excluded.
I highly appreciate your replies!
You should try something like this:
$date = Carbon::today()->subDays(1)->startOfDay();
DB::connection('mysql_prod')->table('companies')->select('companies.symbol')
->leftJoin('trx', 'trx.companies_id', '=', 'companies.id')
->where('trx.transaction_date', '>=', $date)
->whereNotIn('companies.symbol', function ($q) use ($date) => {
$q->select('companies.symbol')
->from('companies')
->leftJoin('articles', 'articles.companies_id', 'companies.id')
->where('articles.created_at', '>', $date)
->distinct()
->get()
})
->orderBy('transaction_date', 'desc')
->distinct()
->get();
It will provide a similar query as you mentioned.
Reference from here.
Also, you can read how to write sub Query from Laravel docs.
Check this one more good answer for that what you need.
I need to do select as the following
select * from table where (x = 1 OR y = 1) AND starting_at < '2018-05-01'
How to do that please.
DB::table('tableName')
->where(function ($query) {
$query->where('x', '=', 1)
->orWhere('y', '=', '1');
})
->where('starting_at', '<', '2018-05-01')
->get();
Im trying days to understand how I can convert a SQL query to a query builder style in laravel.
My SQL query is:
$tagid = Db::select("SELECT `id` FROM `wouter_blog_tags` WHERE `slug` = '".$this->param('slug')."'");
$blog = Db::select("SELECT *
FROM `wouter_blog_posts`
WHERE `published` IS NOT NULL
AND `published` = '1'
AND `published_at` IS NOT NULL
AND `published_at` < NOW()
AND (
SELECT count( * )
FROM `wouter_blog_tags`
INNER JOIN `wouter_blog_posts_tags` ON `wouter_blog_tags`.`id` = `wouter_blog_posts_tags`.`tags_id`
WHERE `wouter_blog_posts_tags`.`post_id` = `wouter_blog_posts`.`id`
AND `id`
IN (
'".$tagid[0]->id."'
)) >=1
ORDER BY `published_at` DESC
LIMIT 10
OFFSET 0");
Where I now end up to convert to the query builder is:
$test = Db::table('wouter_blog_posts')
->where('published', '=', 1)
->where('published', '=', 'IS NOT NULL')
->where('published_at', '=', 'IS NOT NULL')
->where('published_at', '<', 'NOW()')
->select(Db::raw('count(*) wouter_blog_tags'))
->join('wouter_blog_posts_tags', function($join)
{
$join->on('wouter_blog_tags.id', '=', 'wouter_blog_posts_tags.tags_id')
->on('wouter_blog_posts_tags.post_id', '=', 'wouter_blog_posts.id')
->whereIn('id', $tagid[0]->id);
})
->get();
I have read that I can't use whereIn in a join. The error i now get:
Call to undefined method Illuminate\Database\Query\JoinClause::whereIn()
I realy dont know how I can convert my SQL to query builder. I hope when I see a good working conversion of my query I can understand how I have to do it next time.
This work for me:
DB::table('wouter_blog_posts')
->whereNotNull('published')
->where('published', 1)
->whereNotNull('published_at')
->whereRaw('published_at < NOW()')
->whereRaw("(SELECT count(*)
FROM wouter_blog_tags
INNER JOIN wouter_blog_posts_tags ON wouter_blog_tags.id = wouter_blog_posts_tags.tags_id
WHERE wouter_blog_posts_tags.post_id = wouter_blog_posts.id
AND id
IN (
'".$tagid."'
)) >=1")
->orderBy('published_at', 'desc')
->skip(0)
->take(10)
->paginate($this->property('postsPerPage'));
The following Query Builder code will give you the exact SQL query you have within your DB::select:
DB::table('wouter_blog_posts')
->whereNotNull('published')
->where('published', 1)
->whereNotNull('published_at')
->whereRaw('`published_at` < NOW()')
->where(DB::raw('1'), '<=', function ($query) use ($tagid) {
$query->from('wouter_blog_tags')
->select('count(*)')
->join('wouter_blog_posts_tags', 'wouter_blog_tags.id', '=', 'wouter_blog_posts_tags.tags_id')
->whereRaw('`wouter_blog_posts_tags`.`post_id` = `wouter_blog_posts`.`id`')
->whereIn('id', [$tagid[0]->id]);
})
->orderBy('published_at', 'desc')
->skip(0)
->take(10)
->get();
The subquery condition had to be reversed because you can't have a subquery as the first parameter of the where method and still be able to bind the condition value. So it's 1 <= (subquery) which is equivalent to (subquery) >= 1. The query generated by the above code will look like this:
SELECT *
FROM `wouter_blog_posts`
WHERE `published` IS NOT NULL
AND `published` = 1
AND `published_at` IS NOT NULL
AND `published_at` < Now()
AND 1 <= (SELECT `count(*)`
FROM `wouter_blog_tags`
INNER JOIN `wouter_blog_posts_tags`
ON `wouter_blog_tags`.`id` =
`wouter_blog_posts_tags`.`tags_id`
WHERE `wouter_blog_posts_tags`.`post_id` =
`wouter_blog_posts`.`id`
AND `id` IN ( ? ))
ORDER BY `published_at` DESC
LIMIT 10 offset 0
My process when creating more complex queries is to first create them and try them out in a SQL environment to make sure they work as indended. Then I implement them step by step with the Query Builder, but instead of using get() at the end of the query, I use toSql() which will give me a string representation of the query that will be generated by the Query Builder, allowing me to compare that to my original query to make sure it's the same.
I want to query Laravel DB for something like
SELECT * FROM `tickets`
WHERE (created_at > '2015-07-01'
AND created_at < '2015-07-31')
AND (state != 'Resolved'
OR state != 'closed'
OR state != 'Cancelled'
OR state != 'Solution Rejected')
ORDER BY `id` DESC
I tried using raw statements but doesn't seem to work. So I'm trying to use Laravel's own model functions to archive the same result, but I'm missing something... here's what I got so far.
Ticket::whereBetween('created_at', [$start, $end])
->whereIn('state',['Resolved','closed','Cancelled','Solution Rejected'])
->get();
PS: alternatively is there a way I can have this instead
SELECT * FROM `tickets`
WHERE ( (created_at > '2015-07-01'
AND created_at < '2015-07-31')
OR (updated_at > '2015-07-01'
AND updated_at < '2015-07-31') )
AND (state != 'Resolved'
OR state != 'closed'
OR state != 'Cancelled'
OR state != 'Solution Rejected')
ORDER BY `id` DESC
Try this one sir:
DB::table('tickets')
->whereBetween('created_at',[$start, $end])
->orWhere(function($query)
{
$query->where('state', '!=', 'Resolved')
->where('state', '!=', 'closed')
->where('state', '!=', 'Cancelled')
->where('state', '!=', 'Solution Rejected')
->orderBy('id', 'desc');
})
->get();