Reputation: 78
Ok, so I've got a 'users' table with an 'id' column and a 'score' column. 'id' is the primary key, 'score' can be any positive integer, and users can have the same score.
I need to select 3 rows:
Any suggestions on how to do this in SQL? Thanks!
UPDATE
Sorry all, I realize now that I need to make more choices about how to handle multiple rows with the same score. I've decided that tying scores will be excluded, so I'm looking for a user with the next highest score and next lowest score from the target user.
Sample data:
id score
1 0
2 5
3 9
4 5
5 5 *
6 5
7 8 *
8 3 *
So, if my target user has id = 5, I want rows with ids 7, 5, and 8
Upvotes: 2
Views: 4423
Reputation: 38745
Because I need formatting to discuss Andomar's proposal:
Given some users with same score (6):
mysql> select * from sam1vp;
+------+-------+
| user | score |
+------+-------+
| 40 | 5 |
| 41 | 6 |
| 42 | 6 |
| 43 | 6 |
| 44 | 7 |
+------+-------+
A query with >
/ <
will not return the nearest neighbors:
mysql> select user,score from sam1vp where score > 6 order by score limit 1;
+------+-------+
| user | score |
+------+-------+
| 44 | 7 |
+------+-------+
Using >=
/ <=
and excluding the target user will:
mysql> select user,score from sam1vp where score >= 6 and user != 42 order by score limit 1;
+------+-------+
| user | score |
+------+-------+
| 41 | 6 |
+------+-------+
Upvotes: 0
Reputation: 143
select name, score
from users
where id >= select id
from users
where id < 42
order score
limit 1
order by score
limit 3
Upvotes: 0
Reputation: 138960
set @ID = 3;
set @Score = (select score
from users
where ID = @ID);
select ID, Score
from (select U.ID, U.Score
from users as U
where U.ID <> @ID and
U.Score < @Score
order by U.Score desc limit 1) as P
union all
select U.ID, U.Score
from users U
where U.ID = @ID
union all
select *
from (select U.ID, U.Score
from users as U
where U.ID <> @ID and
U.Score > @Score
order by U.Score limit 1) as A
order by Score;
Upvotes: 1
Reputation: 12329
I suppose one problem might be that you could have more than three users of the same score, and you would not know who is "directly above" or "directly below" the target.
You might consider a subquery. The inner query would be something like
select score from users where last='Who' and first='Doctor'
For the outer query, this would get you the one directly above:
select * from users
where score >= (select score from users where last='Who' and first='Doctor')
order by score asc
limit 1
I will leave the user directly below as an exercise to the OP.
Upvotes: 0
Reputation: 238078
First, query the score for that particular user:
select score
from users
where id = 42
Say the score for user 42 is 6. You can then query the next user like:
select name
, score
from users
where score > 6
order by
score
limit 1
and the previous user like:
select name
, score
from users
where score < 6
order by
score desc
limit 1
Upvotes: 2