mysql - 使用复杂查询的排名系统: more precise filters

标签 mysql sql subquery ranking

为了在我的游戏服务器上实现排名系统,我将每个玩家的一些信息存储在 MySQL 数据库中。 我有以下数据库表。

带有示例数据的表玩家:

id | steamId | deaths
---+---------+-------
1  | asdja   | 2
2  | kfjsl   | 5

带有示例数据的表武器:

playerId | weaponId | kills
---------+----------+------
1        | 5        | 8
1        | 9        | 7
2        | 3        | 3
2        | 6        | 10
2        | 7        | 2

您会看到,我没有将每个玩家的击杀数存储在 players 表中,因为我可以简单地从 weapons 表中计算出来。 我对 SQL 查询不太熟悉,但我完成了以下查询来选择具有以下字段的简单数据集:

kills,
deaths,
kill-death-rate (kdrate),
count (maximum number of players),
rank (current ranking position, sorted by kills)

查询:

SELECT
    SUM(weapons.kills) AS `kills`,
    `deaths`,
    (SUM(kills) / IF(deaths, deaths, 1)) AS `kdrate`,
    (SELECT COUNT(*) FROM `players`) AS `count`,
    (
        SELECT
            COUNT(*)
        FROM
            (
                SELECT
                    p.id AS id2,
                    SUM(w.kills) AS kills2,
                    p.deaths AS deaths2,
                    p.steamId AS steamId2
                FROM
                    weapons AS w,
                    players AS p
                WHERE
                    p.id = w.playerId
                GROUP BY
                    p.id
            ) AS temp
        WHERE
            temp.kills2 >= (
                SELECT
                    SUM(weapons.kills) AS `kills`
                FROM
                    `players`,
                    `weapons`
                WHERE
                    players.id = weapons.playerId AND
                    `id` = 1
                GROUP BY
                  `id`
            )
        ORDER BY
            temp.kills2 DESC,
            temp.deaths2 ASC,
            temp.steamId2 ASC
    ) AS `rank`
FROM
    `players`
INNER JOIN
    `weapons`
ON
    players.id = weapons.playerId
WHERE
    `id` = 1
GROUP BY
    `id`

有两个问题:

1.) 查询很糟糕。

2.) 使用给定的示例数据执行此查询会产生“相同的排名”。 我的意思是,两名玩家获得相同的排名,因为两名玩家的击杀数相同。 但相反,玩家 1 应该处于排名 1,因为他的死亡次数比玩家 2 少。 我不知道如何才能实现这一点。

提前致谢!

编辑: @Manueru_mx 给了我如何做到这一点的基本想法: 我根据他的回答得到了以下代码:

SELECT
    id,
    kills,
    deaths,
    kdrate,
    COUNT(*) AS rank,
    (SELECT COUNT(*) FROM players) AS `count`
FROM
    (
        SELECT
            pys.id AS id,
            SUM(wps.kills) AS kills,
            pys.deaths AS deaths,
            (SUM(wps.kills) / pys.deaths) as kdrate
        FROM
            players pys
        INNER JOIN
            weapons wps
        ON
            pys.id = wps.playerid
        GROUP BY
            pys.id
        ORDER BY
            2 DESC,
            3,
            4 ASC
    ) AS tmp
WHERE
    id = 1

剩下的唯一问题是,两种情况下的排名都是1。

最佳答案

这是我的“解决方案”。这个查询更简单,但得到你正在寻找的结果

select 
pys.steamID, SUM(wps.kills) as Kills,
SUM(pys.deaths) as Deaths,
(sum(wps.kills)/sum(pys.deaths)) as kdratio
--,COUNT(pys.steamID) as PlayersC
from players pys
inner join  weapons wps on pys.id = wps.playerid
group by pys.steamID
order by 2 DESC, 3, 4 ASC

添加排名。

SELECT
    id,
    kills,
    deaths,
    kdrate,
    ranking_usr as rank,
    (SELECT COUNT(*) FROM players) AS `count`
FROM
    (
        SELECT
            @row := @row + 1 AS ranking_usr
            pys.id AS id,
            SUM(wps.kills) AS kills,
            pys.deaths AS deaths,
            (SUM(wps.kills) / pys.deaths) as kdrate
        FROM
            players pys
        INNER JOIN
            weapons wps
        ON
            pys.id = wps.playerid
        GROUP BY
            pys.id
        ORDER BY
            2 DESC,
            3,
            4 ASC
    ) AS tmp
WHERE
    id = 1

关于mysql - 使用复杂查询的排名系统: more precise filters,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12976162/

相关文章:

php - 更新从 mysql 获取的表单值

sql - 查找多列中具有相同值的行

mysql - 如何从本地数据库更新在线数据库上的数据

mysql - SELECT 类型查询是唯一可以嵌套的类型吗?

mysql - 如何限制查询用户引起的潜在mysql性能问题?

mysql - sql查询获取最新的调用

sql - 使用 Oracle 函数从字符串中提取数字

sql - SQL中,如果只想求交集,总能写一条内连接语句作为主查询和子查询吗?

mysql - 将使用子查询的查询重写为使用联接的查询时导致 SQL 错误

mysql - 错误 : select command denied to user '<userid>' @'<ip-address>' for table '<table-name>'