When a post is accessed, I need, in addition to returning the information of this posts, to return the previous one if it exists and the next one.
I would like to know if there is a way to select MAX(id)
and MIN(id)
in a single query/select, passing a condition for each one of them. Example of what I’m trying to do in Laravel and I’ll write it in SQL to make it easier too
Laravel:
$query = Post::query();
$query = $query->from('posts')->select(DB::raw('MAX(id), MIN(id)'))->whereRaw("id < {$id} and id > {$id}")->first();
SQL:
select MAX(id), MIN(id) from `posts` where id < 5 and id > 5 limit 1
The id variable is the post id value. In this example, it has the value 5. The query I’m doing is to get the MAX and MIN referring to this id, but I also need to get the info of the post that the user accessed.
The DB has post id number 4 and number 6. That is, I need to get the information from posts number 4, 5 and 6 in this example.
The where condition will never be true
, but I cannot use or
. The first condition is for MAX
and the second for MIN
. If I use the or
, the biggest id will come of the DB.
I need to get the min and max value compared to a value. That is, as I explained above. If the id is 5, I need to get the largest existing id() below that value and I need to get the smallest value above it. In my case, from the information I have in the DB, it would be id 4, 5 and 6
Is it possible in a single consultation or do I really have to do more than one?
3
Answers
The LEAD() and LAG() function in MySQL are used to get preceding and succeeding value of any row within its partition.
Try this:
Yes, you can do it with
case-when
EDIT
Laravel equivalent, as shared by Gabriel Edu in the comment-section:
You may use
lead
andlag
to access the values before and after the current row.You may then use those to select the post with a given id and the values before and after in a single select.
The following query
results in
With the following setup:
Schema (MySQL v8.0)
View on DB Fiddle