Таблица лидеров, запрос ранга, как вернуть строки выше / ниже ранга пользователя


Учитывая этот запрос, если я хочу вытащить ранг конкретного человека, где я знаю, что есть $name и $score, и вернуть строки выше / ниже этого ранга (скажем, + / - 4), Как я буду это делать?

$query = "SELECT @curRank := @curRank + 1 AS Rank,
            uniqueID,
            name,
            score
        FROM scores, (SELECT @curRank := 0) r
        ORDER by score DESC";

Я пишу на php, используя MySQL и C# в Unity. Моя игра делает звонок на сервер и запускает php-код. Цель состоит в том, чтобы повторить информацию и проанализировать информацию обратно в игре.

Любая помощь будет очень признательна :)

1 3

1 ответ:

Основываясь на вашем :=, я предполагаю, что вы используете PostgreSQL, правильно? Я больше знаком с синтаксисом T-SQL; но, несмотря на это, и PostgreSQL, и T-SQL имеют оконные функции. Вы можете реализовать что-то похожее на следующее (Я оставил переменные для заполнения):

$query = "WITH scoreOrder
    AS
    (
        SELECT uniqueID,
            name,
            score,
            ROW_NUMBER() OVER (ORDER BY score DESC, uniqueID DESC) AS RowNum
        FROM scores
        ORDER BY uniqueID DESC
    )
    SELECT ns.*
    FROM scoreOrder ms --Your matching score
    INNER JOIN scoreOrder ns --Your nearby scores
    ON ms.name = /* your name variable */
        AND ms.score = /* your score variable */
        AND ns.RowNum BETWEEN ms.RowNum - /* your offset */ and ms.RowNum + /* your offset */";
Пояснение: во-первых, мы создаем общее табличное выражение под названием scoreOrder и проектируем столбец RowNum для ваших оценок. Короче говоря, ROW_NUMBER() OVER (ORDER BY score DESC, uniqueID DESC) просто говорит: "Я возвращаю номер строки эта запись заказана score и uniqueID, как по убыванию, так и в таком порядке.- Тогда ты присоединишься к этому CTE вместе с ним самим... ms будет ваш счет, который вы сопоставляете, и вы соединяете , который С ns, где ns.RowNum будет между вашим ms.RowNum, плюс или минус ваше смещение. Существует масса других оконных функций. Вот некоторые другие, которые могут быть более или менее подходящими для вашего сценария:
  • ROW_NUMBER() - номер строки запись
  • RANK() - ранг записи, дублирующейся в связях и включающей пробелы (то есть, если 2-е место связывает, у вас будет 1-е, 2-е, 2-е, 4-й )
  • DENSE_RANK() - то же, что и Ранг, за исключением того, что он заполняет пробелы (то есть, если 2-е место связывает, у вас будет 1-е, 2-е, 2-е, 3-е)

Для получения дополнительной информации, проверьте документацию PostgreSQL по оконным функциям и их учебник

Обновление:

К сожалению, MySQL не поддерживает оконные функции или общие табличные выражения. В вашем сценарии вам придется поместить результаты предыдущего запроса во временную таблицу, а затем выполнить аналогичное объединение, как показано выше. Так, например...

CREATE TEMPORARY TABLE IF NOT EXISTS allRankings AS 
(
  SELECT @curRank := @curRank + 1 AS Rank,
        uniqueID,
        name,
        score
    FROM scores, (SELECT @curRank := 0) r
    ORDER by score DESC, uniqueID
);

SELECT r.*
FROM allRankings r 
INNER JOIN allRankings myRank
ON r.Rank BETWEEN myRank.Rank - <your offset>  AND myRank.Rank + <your offset>
    AND myRank.name = <your name> 
    AND myRank.score = <your score> 
ORDER by r.Rank;

Вот ссылка SQLFiddle для примера. (я не использую временную таблицу на SQLFiddle, потому что вам нужно построить таблицы в окне схемы сборки).