问题
Let's pretend we have this relation:
╔═══════════════════╗
║ i++ name score ║
╠═══════════════════╣
║ 1 Will 123 ║
║ 2 Joe 100 ║
║ 3 Bill 99 ║
║ 4 Max 89 ║
║ 5 Jan 43 ║
║ 6 Susi 42 ║
║ 7 Chris 11 ║
║ 8 Noa 9 ║
║ 9 Sisi 4 ║
╚═══════════════════╝
Now I need a subset based on the data I am searching for. For instance I'm searching for the fith place. In my result I need more than the record of Jan, I need the two records before Jan and the two records behind Jan too. So I have the following resultset:
╔═══════════════════╗
║ id++ name score ║
╠═══════════════════╣
║ 3 Bill 99 ║
║ 4 Max 89 ║
║ 5 Jan 43 ║
║ 6 Susi 42 ║
║ 7 Chris 11 ║
╚═══════════════════╝
That is the sql I got:
select @a:= id from quiz.score where username = 'Jan';
set @i=0;
SELECT @i:=@i+1 as Platz, s.*
FROM quiz.score s where id BETWEEN @a-5 AND @a+5
order by points desc;
The problem here is that @a
is the id
of the record. Is there a way to use the calculated value @i:=@i+1
?
Thx a lot for your help.
回答1:
If you do not need the rank in your output (and it appears from your comments and favored answers that you do not), you can simply combine the quiz scores nearest to Jan's score:
Query (SQL Fiddle here):
-- XXX this assumes `scores`.`username` is UNIQUE !
SELECT * FROM (
-- Get those who scored worse (or tied)
( SELECT s.*
FROM scores s
CROSS JOIN (SELECT score FROM scores WHERE username = 'Jan') ref
WHERE s.score <= ref.score AND username <> 'Jan'
ORDER BY s.score DESC
LIMIT 2)
UNION
-- Get our reference point record
(SELECT s.* FROM scores s WHERE username = 'Jan')
UNION
-- Get those who scored better
( SELECT s.*
FROM scores s
CROSS JOIN (SELECT score FROM scores WHERE username = 'Jan') ref
WHERE s.score > ref.score AND username <> 'Jan'
ORDER BY s.score ASC
LIMIT 2)
) slice
ORDER BY score ASC;
(Note that I LIMITed the results to two records before Jan and two after Jan because your sample data set was so small.)
Those parentheses on the constituent queries above are needed to allow LIMIT and UNION to work together. The outermost query then lets us ORDER the results of a UNION.
回答2:
It's not entirely clear what you want, but a creative use of limit might be able to help:
Set @i = 0;
Select
(@i := @i + 1) + 2 place,
s.*
From
quiz_score s
Order By
quality Desc
Limit
2, 5;
Example Fiddle
回答3:
I have a working solution for you. The main point was to increment variable in WHERE
clause.
The below code displays 7 rows: 3 below 'Jan', 'Jan' itself, and 3 after.
SET @i=0;
SELECT @n:=id, @s:=points FROM Score c WHERE c.username='Jan' ORDER BY points DESC;
SELECT (@i:=@i+1) FROM Score c WHERE c.id <> @n AND c.points <= @s;
SELECT (@i:=@i+1) FROM Dual;
SET @k=0;
SELECT s.* FROM Score s WHERE (@k:=@k+1) >= @i-3 AND @k<= @i+3 ORDER BY points DESC;
SQL Fiddle
Let me know if any clarifications are required.
来源:https://stackoverflow.com/questions/19211700/sql-show-partition-based-on-calculated-column-with-mysql