You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用单条SQL查询获取排行榜中用户及前后相邻排名用户?

用单条SQL获取排行榜中当前用户的相邻用户

当然可以用单条SQL搞定这个需求!不用分开跑两次查询,咱们有两种靠谱的方法实现,看完你就懂了~

方法一:用UNION ALL合并三个查询

这个方法和你现在用的两条查询逻辑很接近,只是把当前用户的查询也加进去,用UNION ALL合并成一条语句,一次性拿到三个用户的数据:

-- 先取当前用户的数据
SELECT * FROM users WHERE id = [USER.ID]
UNION ALL
-- 取积分更高(或同积分)的相邻用户:找比当前用户积分高的最小值,同积分则取id相邻的
SELECT TOP 1 * 
FROM users 
WHERE (points > [USER.POINTS]) OR (points = [USER.POINTS] AND id != [USER.ID])
ORDER BY points ASC, id ASC
UNION ALL
-- 取积分更低(或同积分)的相邻用户:找比当前用户积分低的最大值,同积分则取id相邻的
SELECT TOP 1 * 
FROM users 
WHERE (points < [USER.POINTS]) OR (points = [USER.POINTS] AND id != [USER.ID])
ORDER BY points DESC, id DESC

我稍微调整了条件,主要是处理同积分用户的情况——如果只写points >=,可能会拿到一堆同积分的用户,加上OR (points = [USER.POINTS] AND id != [USER.ID])再按id排序,能确保取到真正相邻的同积分用户,避免逻辑漏洞。

方法二:用窗口函数(更优雅,推荐)

如果你的数据库支持窗口函数(比如SQL Server 2012+、MySQL 8+、PostgreSQL这些主流数据库都支持),用LAG()和LEAD()函数能写出更简洁、易维护的SQL:

WITH ranked_users AS (
    SELECT 
        *,
        -- 拿到当前用户的「上一位」(积分更高/同积分的前一个用户ID)
        LAG(id) OVER (ORDER BY points DESC, id ASC) AS prev_user_id,
        -- 拿到当前用户的「下一位」(积分更低/同积分的后一个用户ID)
        LEAD(id) OVER (ORDER BY points DESC, id ASC) AS next_user_id
    FROM users
)
-- 关联users表,取出当前用户、上一位、下一位的完整数据
SELECT u.*
FROM ranked_users r
JOIN users u ON u.id IN (r.id, r.prev_user_id, r.next_user_id)
WHERE r.id = [USER.ID]

这个思路是先给所有用户按积分降序、id升序排好序(积分相同的用户按id稳定排序),然后用LAG()获取当前用户的前一个用户ID,LEAD()获取后一个用户ID,最后通过关联查询把这三个用户的数据捞出来。

小提醒

  • 如果当前用户是排行榜第一名,prev_user_id会是NULL,结果里只会有当前用户和下一位;同理如果是最后一名,next_user_id是NULL,结果里只有当前用户和上一位。
  • 排序规则里加id ASC是为了让同积分用户有固定的排名顺序,避免相邻用户随机变化。

内容的提问来源于stack exchange,提问作者Chris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:41:42