我已经为此苦苦挣扎了一段时间,但还没有找到解决方案。
我有一个 MySQL 数据库表,其中包含游戏角色数据,具有以下列:
- 角色ID:玩家死亡后,他会获得新角色,从而添加新条目。
- PlayerUID:每个玩家都是唯一的。需要按此分组。
- KillsZ:显示每个角色的击杀次数。
- 世界空间:角色的位置。
- 活着:角色是活着还是死了?
所以我需要一个 SQL 查询来返回玩家的总击杀数及其当前角色的坐标。我怎样才能做到这一点?
我认为应该是这样:
SELECT CharacterID, PlayerUID, sum(KillsZ), Worldspace, alive
FROM character_data
WHERE Worldspace IN (SELECT Worldspace FROM character_data WHERE alive = 1)
GROUP BY PlayerUID
ORDER BY sum(KillsZ) DESC;
输出:(顶部 11 行)
"CharacterID" "PlayerUID" "sum(KillsZ)" "Worldspace" "alive"
"924" "76561198042033373" "88" "[128,[8438.99,3093.65,7.408]]" "1"
"509" "76561198117519944" "78" "[234,[4284.56,6222.69,-4.425e-04]]" "1"
"1360" "76561198046918433" "63" "[194,[8735.35,5139.39,16.179]]" "1"
"1457" "76561197988106961" "46" "[146,[8740.07,5089.61,0.278]]" "1"
"606" "76561198050960639" "40" "[317,[4523.15,1815.6,0.889]]" "1"
"1413" "76561198053078285" "37" "[303,[5908.08,2024.8,0.002]]" "1"
"597" "76561198118406618" "36" "[338,[4433.23,1619.99,0.001]]" "1"
"99" "76561197988519309" "32" "[]" "0"
"1384" "76561198088203111" "31" "[205,[2334.34,8904.73,0.001]]" "1"
"375" "76561197965753706" "30" "[307,[3962.21,7522.75,7.299]]" "1"
"1364" "76561198013225036" "28" "[195,[8452.11,3093.67,0.198]]" "1"
这是没有以下内容的查询:
SELECT CharacterID, PlayerUID, sum(KillsZ), Worldspace, alive
FROM character_data
GROUP BY PlayerUID
ORDER BY sum(KillsZ) DESC;
输出:(顶行 11 行)
"CharacterID" "PlayerUID" "sum(KillsZ)" "Worldspace" "alive"
"14" "76561198034271930" "982" "[96,[6462.44,3728.73,0]]" "0"
"3" "76561198053078285" "754" "[106,[6024.94,1215.49,0]]" "0"
"12" "76561197988519309" "427" "[147,[2387.11,4747.59,0.002]]" "0"
"48" "76561198022644097" "383" "[11,[7879.52,1695.43,3.368]]" "0"
"636" "76561198055683105" "344" "[184,[5063.51,3356.11,0.001]]" "0"
"635" "76561198084556053" "312" "[311,[8730.96,5077.45,0.001]]" "0"
"855" "76561198096335334" "262" "[191,[7116.15,2484.91,0]]" "0"
"560" "76561198082709294" "247" "[234,[1967.64,5471.63,0.002]]" "0"
"8" "76561198154755873" "217" "[99,[5438.96,3317.55,0.002]]" "0"
"96" "76561197961156126" "206" "[117,[2597.8,3383.29,0.876]]" "0"
"806" "76561198007739284" "180" "[312,[6502.08,3744.86,0.003]]" "0"
您可以看到总击杀数不同。
最佳答案
当您GROUP BY
结果集时,标准 SQL 要求对 GROUP BY
子句中没有的任何列使用聚合函数。这是因为每个组对应多个行,非分组列中具有不同(或可能不同)的值。您的查询引用了以下哪些值?其他 DBMS 不会处理像您问题中那样的模糊查询,但是 MySQL allows you to do this假设只有当非分组列中的所有可能值在组内均为常数时才会执行此操作。
听起来您想要与玩家关联的所有角色的总击杀数,这就像对每个组的 KillsZ
列求和一样简单:
SELECT
PlayerUID,
SUM(KillsZ) AS TotalKills
FROM character_data
GROUP BY PlayerUID;
要添加当前事件角色的坐标,您可以使用 CASE
表达式将每行中与死角色对应的坐标设为无效,然后使用聚合函数 MAX
获取剩下的单个值:
SELECT
PlayerUID,
SUM(KillsZ) AS Total_Kills,
MAX(CASE WHEN alive = 1 THEN Worldspace END) AS Current_Coordinates
FROM character_data
GROUP BY PlayerUID;
这是一个简单的查询,仅对数据进行一次传递,并且可以通过适当的覆盖索引来满足(如果性能需要的话)。相比之下,建议将表外部连接到自身的解决方案相当复杂,但如果很重要的话,可以通过较小的索引来满足。这两种解决方案之间的一个重要区别是,我的解决方案将向您显示只有死亡角色的玩家,而目前编写的另一种则不会。
这依赖于一个重要的假设,即在任何给定时间,任何组中只有一行具有 alive = 1
。您可能需要考虑在数据库中强制执行此约束。只要玩家在数据库中最多只能拥有一个活着的角色,您就会从 MAX
或 MIN
获得相同的结果,并且可以使用其中之一。如果您的坐标值是数字,您甚至可以使用 SUM
,尽管我认为这会有点误导(如果您的坐标存储为 CHAR 类型,则它将不起作用)。
在 MySQL 中,您可以用 IF(alive = 1, Worldspace, NULL)
替换这个简单的 CASE
表达式,但由于这样的可移植性较差,而且冗长程度也没有明显降低,所以我建议坚持使用 CASE
,它是 SQL 标准的一部分。
关于MySQL:组玩家UID,显示总击杀数和活着角色的最新坐标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26852982/