Не знаю как кто, а я, если нахожу простое решение к какой-либо задаче, то всегда возникает желание этим решением с кем-нибудь поделиться. Так и сегодня, решив поставленную задачу, хотел бы поделиться ее решением.
Суть задачи проста: есть некий рейтинг пользователей. Необходимо показать пользователю его текущее положение, а также положение его ближайших конкурентов. Проще говоря, показать N-5..N+5 позиций в рейтинге, где N положение пользователя в рейтинге.
Таблица с рейтингами пользователей содержит четыре поля: id, points, time, uid и answered. Нас будут интересовать только два поля: points и time по которым и строится рейтинг.
Очевидно, что одним запросом здесь не обойтись, поэтому сразу создадим хранимую процедуру get_user_rating(user_id), которая будет получать рейтинг пользователя.
Так как нам понадобиться возвращать результат из процедуры, а именно выборку, состоящую из [6..11] строк, то для ее хранения будем использовать временную таблицу, создаваемую при вызове процедуры. К слову сказать, получить результат запроса, выполненного в теле хранимой процедуры, можно и другим способом, но мы не будем его сейчас затрагивать.
Далее мы выбираем баллы пользователя:
Теперь, используя полученное выше значение, выбираем близлежащие 5 строк с большим и 5 строк с меньшим значением баллов.
и
Объединим все три результата и вставим в нашу временную таблицу. Получим результирующую хранимую процедуру:
Главное не забыть отсортировать результат объединения. Теперь в приложении получаем наш рейтинг:
Готово. Надеюсь данная информация окажется полезной.
Суть задачи проста: есть некий рейтинг пользователей. Необходимо показать пользователю его текущее положение, а также положение его ближайших конкурентов. Проще говоря, показать N-5..N+5 позиций в рейтинге, где N положение пользователя в рейтинге.
Таблица с рейтингами пользователей содержит четыре поля: id, points, time, uid и answered. Нас будут интересовать только два поля: points и time по которым и строится рейтинг.
Очевидно, что одним запросом здесь не обойтись, поэтому сразу создадим хранимую процедуру get_user_rating(user_id), которая будет получать рейтинг пользователя.
- drop procedure if exists get_user_rating //
- create procedure get_user_rating (in uid int unsigned)
- end //
* This source code was highlighted with Source Code Highlighter.
Так как нам понадобиться возвращать результат из процедуры, а именно выборку, состоящую из [6..11] строк, то для ее хранения будем использовать временную таблицу, создаваемую при вызове процедуры. К слову сказать, получить результат запроса, выполненного в теле хранимой процедуры, можно и другим способом, но мы не будем его сейчас затрагивать.
- drop procedure if exists get_user_rating //
- create procedure get_user_rating (in uid int unsigned)
- begin
- drop table if exists rating_tmp;
- create temporary table rating_tmp (
- `points` int unsigned,
- `time` int unsigned,
- `uid` int unsigned,
- `answered` int unsigned
- );
- end //
* This source code was highlighted with Source Code Highlighter.
Далее мы выбираем баллы пользователя:
- select @points := points from rating r where r.uid = uid;
* This source code was highlighted with Source Code Highlighter.
Теперь, используя полученное выше значение, выбираем близлежащие 5 строк с большим и 5 строк с меньшим значением баллов.
- select h.points, h.time, h.uid, h.answered
- from rating h
- where @points < h.points
- order by h.points desc, h.time desc
- limit 5
* This source code was highlighted with Source Code Highlighter.
и
- select b.points, b.time, b.uid, b.answered
- from rating b
- where @points > points
- order by b.points desc, b.time desc
- limit 5)
* This source code was highlighted with Source Code Highlighter.
Объединим все три результата и вставим в нашу временную таблицу. Получим результирующую хранимую процедуру:
- drop procedure if exists get_user_rating //
- create procedure get_user_rating (in uid int unsigned)
- begin
- drop table if exists rating_tmp;
- create temporary table rating_tmp (
- `points` int unsigned,
- `time` int unsigned,
- `uid` int unsigned,
- `answered` int unsigned
- );
-
- select @points := points from rating r where q.uid = uid;
-
- insert into rating_tmp (points, `time`, uid, answered)
- (select h.points, h.time, h.uid, h.answered
- from rating h
- where @points < h.points
- order by h.points desc, h.time desc
- limit 5)
-
- union
- (select points, `time`, uid, answered from rating r1 where r1.uid = uid)
- union
-
- (select b.points, b.time, b.uid, b.answered
- from rating b
- where @points > points
- order by b.points desc, b.time desc
- limit 5)
-
- order by points desc, `time` desc;
- end //
* This source code was highlighted with Source Code Highlighter.
Главное не забыть отсортировать результат объединения. Теперь в приложении получаем наш рейтинг:
- call get_user_rating(1);
-
- seleсt * from rating_tmp;
* This source code was highlighted with Source Code Highlighter.
Готово. Надеюсь данная информация окажется полезной.