@Tutucu

Как отсортировать данные и получить 10 элементов ДО и 10 элементов ПОСЛЕ в Laravel?

Всем привет! Делаю рейтинг игроков в игре на , никак не могу допетрить как в минимальное количество запросов сделать следующее:
Получить место игрока по id в общем рейтинге и получить ТОЛЬКО 10 игроков, которые имеют очков больше текущего игрока и 10 игроков, у которых их меньше, итого нужно получить 21 элемент из базы данных, где в центре будет текущий игрок. Использую конструктор запросов Laravel.
Структура таблицы по рейтингу:
[id] [user_id] [score]
1 1 0
2 2 50
3 3 0
4 4 280
5 5 1005
6 6 2000 
и т.д.

Хочу получить:
[id] [user_id] [score]
<тут ещё  8 игроков>
38 38 2545
6 6 2000
5 5 1005 - это нужный игрок (в центре выборки)
4 4 280
2 2 50
<тут ещё  8 игроков>
  • Вопрос задан
  • 120 просмотров
Решения вопроса 1
Fernus
@Fernus
Техник - Механик :)
Попробуй так...кроме условия score...как ты в коммах пишешь, можно и дату добавить в orderBy...для случаев с одинаковыми...
<?php

$rsUser = Model::where('user_id', ID_ЮЗЕРА)->first();

if($rsUser) {

    DB::statement(DB::raw('set @row := 0'));

    $rsFirst2Before = Model::where('score', '<=', $rsUser->score)->orderBy('score', 'DESC')->select(['*', DB::raw('@row := @row + 1 as `row`')])->limit(11);
    $rsAfter = Model::where('score', '>=', $rsUser->score)->where('user_id', '<>', $rsUser->user_id)->orderBy('score', 'ASC')->select(['*', DB::raw('@row : = @row + 1 as `row`')])->limit(10);
    
    $rs = $rsFirst2Before->union($rsAfter)->get();

    // dump($rs);
    
}

?>


P.S.: В моём ответе подразумевается ещё и порядковый номер в рейтинге среди всех...
Если вообще это работать будет :) Я не тестил, но должно))
Проверяй))

Порядковый номер по ключу row будет доступен...

UPD:
Ещё немного подправил ответ...там добавил where('user_id', '<>', $rsUser->user_id), чтобы не было "в последующих 10" одного и того же юзера, если есть с одинаковым рейтингом...

UPD2:
Хотя и тут есть нюанс...если будет, например, 30 юзеров с одинаковым рейтингом...
Короче, если это сработает, дальше разберёмся, чтобы до идеала довести :)

UPD3:
Ещё рассмотрите вариант с временной таблицей...в которую раз в какое-то время (или по событию) сразу записывать юзеров и их места...
По мне так - это самый лучший вариант...
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
что-то типа
SELECT score INTO @score FROM players WHERE id = :p_id;
SELECT * FROM (SELECT * FROM players p WHERE points > @score ORDER BY score LIMIT 10) ORDER BY score DESC
UNION
SELECT * FROM players WHERE points <= @score ORDER BY score DESC LIMIT 11;
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы