Оптимизация SQL запроса при выборе только лучших игроков

Рейтинг: 1Ответов: 1Опубликовано: 16.08.2023

По умолчанию, я выгружаю всю базу данных и сортирую лучших игроков по процентам побед. Но это грубая ошибка, когда в базе будет очень много зарегистрированных пользователей. Возможно ли выбрать 100 лучших игроков, по процентам побед прямо в SQL запросе? Чтобы я выгрузил только их.

Server version: 8.0.31 MySQL Community Server - GPL
Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Запрос:

public async Task<IEnumerable<PlayerRankData>> GetRankByWinRate()
{
    try
    {
        return await Db.QueryAsync<PlayerRankData>("select charactername as CharacterName, objid as ObjId, level as Level, " +
            "crank as PlayerRank, nw as NumberWinners, nl as NumberLosses from characters");
    }
    catch (Exception exception)
    {
        DebugException.Instance.Execute(exception);
        Console.WriteLine($"Method: {nameof(GetRankByWinRate)}. Message: '{exception.Message}'");

        return null;
    }
}

Контракт:

public sealed class PlayerRankData
{
    public string CharacterName { get; set; }
    public long ObjId { get; set; }
    public int Level { get; set; }
    public int PlayerRank { get; set; }
    public int NumberWinners { get; set; }
    public int NumberLosses { get; set; }
    public long TimeWinRate { get; set; }
    public long TimeByLevel { get; set; }
    public long TimeNumberFights { get; set; }
}

Cортировка:

if (_gameClient.PlayerRankDatas == null)
{
    data = await _rankTableRepository.GetRankByWinRate();

    _gameClient.PlayerRankDatas = data.OrderByDescending(
        rate => InternalWinRateCalculate(rate)).Take(_appConfiguration.RankMaxTakePlayers).ToList();
}
else
    _gameClient.PlayerRankDatas = _gameClient.PlayerRankDatas.OrderByDescending(
        rate => InternalWinRateCalculate(rate)).Take(_appConfiguration.RankMaxTakePlayers).ToList();

Ответы

▲ -2Принят
SELECT
    charactername AS CharacterName,
    objid AS ObjId,
    level AS Level,
    crank AS PlayerRank,
    nw AS NumberWinners,
    nl AS NumberLosses
FROM characters
ORDER BY
    CASE WHEN (nw + nl) > 0 THEN nw / (nw + nl) ELSE 0 END DESC
LIMIT 100;