【问题标题】:sql and getting elements around a specific onesql并获取特定元素周围的元素
【发布时间】:2011-06-09 20:22:25
【问题描述】:

我的 sql 数据库存储游戏玩家的高分,如下所示:

playerName
scores

为了显示分数,我正在尝试创建一个查询,该查询为 playerId“joe”返回 joe 的位置以及一个得分比 joe 多和少的玩家:

(rank) (playerName) (scores)
5000    luci       2001
5001    joe        1900
5002    marc       1750

(我在这里添加排名只是为了更清楚。它不存储,仅代表按分数排序时列表中的位置) 有没有办法通过查询来做这样的事情而不会得到一半的数据库作为结果?

【问题讨论】:

  • rank 列似乎很方便...您可以选择 joe 的排名 + 或 - 1 之间的排名吗?
  • @FOSC:排名列目前不存在,因为它是多余的,如果一个用户提交更高的分数,我将不得不更新所有排名行。但目前我正在考虑添加这样一行是否会更好,因为具有多个选择/连接的其他路径对我来说似乎相当复杂。

标签: mysql sql-order-by


【解决方案1】:

您最好使用窗口函数来执行此操作,即row_number()lead()lag()

这些在 MySQL 中不可用,但这里有 a few workarounds(也有 row_number(),来自同一作者)。


使用窗口函数:

with
players as (
select row_number() over w as rank,
       playername,
       scores
from players
window w (order by scores desc)
),
player as (
select rank
from players
where playername = 'joe'
)
select rank,
       playername,
       scores
from players
join player on players.rank between player.rank - 1 and player.rank + 1

或者(稍微快一点):

with
player_range as (
select scores - 100 as scores -- or whatever is large enough based on your stats
from players
where playername = 'joe'
),
players as (
select row_number() over w as rank,
       players.playername,
       players.scores
from players
join player_range
on player_range.scores <= players.scores
window w (order by scores desc)
),
player as (
select rank
from players
where playername = 'joe'
)
select rank,
       playername,
       scores
from players
join player on players.rank between player.rank - 1 and player.rank + 1

【讨论】:

  • 嗯,我尝试了这个,但它们对我来说似乎相当复杂。他们也可能会消耗很多性能,对此不确定。但是感谢您的链接。
  • 如果您需要数据库中的排名/领先/滞后,则无法逃避。是的,使用proper DB engine 时性能会很差。
  • 好的,我将切换到 Postgre 这可能是最好的解决方案。刚刚检查过,我的虚拟主机支持这一点。
  • 我已经更新了答案,这样你就可以看到它是如何在 postgres 中使用 with 语句和窗口函数完成的。
【解决方案2】:

要确定 joe 的排名,您必须查询数据库并按分数排序。

【讨论】:

  • 是的,order by 和 limit 是一个选项,但据我所知,在这种情况下,我会得到 5002 个条目或所有条目,我想知道是否没有更好的性能/更少数据的方法从数据库接收。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-08
  • 2021-11-30
  • 2011-10-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多