Reputation: 1257
I have a news
table, and I want to get all the news
that are started but not ended yet by filtering by the columns start_at
& end_at
:
"select * from `news` where `start_at` <= NOW() and `end_at` >= NOW()"
or as I'm doing in Laravel :
$news = News::where("start_at", '<=', date("Y-m-d"))
->where("end_at", '>=', date("Y-m-d"))->get();
But I also want to ignore filtering by the column end_at
if it is NULL, so if the column is NULL I want the result to be displayed as if I only used this query :
"select * from `news` where `start_at` <= NOW()"
Thanks in advance.
Upvotes: 2
Views: 981
Reputation: 11602
If end_at
is indexed i rather would rather rewrite Madhur Bhaiya's answer
Query
SELECT * FROM news
WHERE start_at <= NOW() AND
(end_at >= NOW() OR end_at IS NULL)
as
Query rewite
SELECT * FROM news
WHERE
start_at <= NOW()
AND
end_at >= NOW()
UNION ALL
SELECT * FROM news
WHERE
start_at <= NOW()
AND
end_at IS NULL
Because OR
tends to optimize much worse then using a UNION ALL
approach.
Oracle database does optimization trick native in the optimizer, still waiting until MySQL also get this optimization trick native in the optimizer as MySQL is owned by Oracle corp.
Upvotes: 2
Reputation: 1733
Thanks to the union Operator, we can do something like this:
$news = News::whereNotNull("end_at")
->where("start_at", '<=', date("Y-m-d"))
->where("end_at", '>=', date("Y-m-d"))
->union
(
News::whereNull("end_at")
->where("start_at", '<=', date("Y-m-d"))
)->get();
Upvotes: 0
Reputation: 3859
You can try with Carbon
:
$news = News::where("start_at", '<=', Carbon::now())
->when('end_at' !== null, function($query){
$query->where("end_at", '>=', Carbon::now())
})
->get();
Upvotes: 1
Reputation: 28834
Simply use AND/OR logical operators, alongwith IS NULL
comparison operator. Query in MySQL would be as follows:
SELECT * FROM news
WHERE start_at <= NOW() AND
(end_at >= NOW() OR end_at IS NULL)
Upvotes: 5