I have table called \"users\" and need to select 2 rows before and after specific row, sorted by users.score ASC
users table (structure):
id name
(SELECT x.* FROM users x JOIN users y ON y.score <= x. score WHERE y.id = 5 ORDER BY score LIMIT 3)
UNION
(SELECT x.* FROM users x JOIN users y ON y.score >= x. score WHERE y.id = 5 ORDER BY score DESc LIMIT 3)
[ORDER BY score] ;
http://www.sqlfiddle.com/#!9/45c22/42
Selecting arbitrarily ordered rows before and after a specific id
SET @j = 0;
SET @i = 0;
SELECT *
FROM (
SELECT id, col1, col2, ..., @j:=@j+1 AS pos
FROM `table`
WHERE col1=... ORDER BY col1 DESC, col2 ASC
) AS zz
WHERE (
SELECT position
FROM (
SELECT id AS id2, @i:=@i+1 AS position
FROM `table`
WHERE col1=... ORDER BY col1 DESC, col2 ASC
) AS zz
WHERE id2=$currId
)
IN (pos-5,pos-4,pos-3,pos-2,pos-1,pos,pos+1,pos+2,pos+3,pos+4,pos+5)
Using union all
and subqueries to limit the records should do it:
select * from users where id = 5
union all (
select * from users
where score < (select score from users where id = 5)
order by score desc limit 2
)
union all (
select * from users
where score > (select score from users where id = 5)
order by score asc limit 2
)
order by score
Sample SQL Fiddle
Edit: I think a better method is to number the rows according to score and then select the rows with number -2 and +2 from the rows of id 5:
select id, name, score
from (select
t.*, @rownum1 := @rownum1 + 1 as rank
from users t, (select @rownum1 := 0) r
order by score
) a,
(select rank from (
select t.*,
@rownum := @rownum + 1 as rank
from users t, (select @rownum := 0) r
order by score
) t
where id = 5
) b
where b.rank between a.rank -2 and a.rank+2
order by score;
Sample SQL Fiddle
I just write the query, based on "jpw" solution (many thanks to him)
select * from users where id = 5
union all (
select * from users
where id in (select id from users where score < (select score from users u where u.id = 5) order by score ASC)
order by score desc limit 2
)
union all (
select * from users
where id in (select id from users where score > (select score from users u where u.id = 5) order by score ASC)
order by score ASC limit 2
)
order by score
Perhaps using union all
(
select * from users where id < 5 order by score limit 2
)
union all
(
select * from users where id > 5 order by score limit 2
)