mysql8.0查询等级排名可使用窗口函数,那5.7的版本呢?

1、需求:查询用户详情的同时查询用户的排名

在这里插入图片描述

2、首先看下数据库表设计

分为会员用户表member_user和会员等级表member_level,升级的条件是根据经验值升级,表结构如下:

用户表 member_user
CREATE TABLE `member_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
  `mobile` varchar(11) DEFAULT NULL COMMENT '手机号',
  `status` tinyint(4) NOT NULL COMMENT '状态',
  `nickname` varchar(30) NOT NULL DEFAULT '' COMMENT '用户昵称',
  `avatar` varchar(512) NOT NULL DEFAULT '' COMMENT '头像',
  `sex` tinyint(4) DEFAULT '0' COMMENT '用户性别',
  `level_id` bigint(20) DEFAULT NULL COMMENT '等级编号',
  `experience` int(11) NOT NULL DEFAULT '0' COMMENT '经验',
  `entry_time` datetime DEFAULT NULL COMMENT '入职时间',
  `hobbies` varchar(200) DEFAULT NULL COMMENT '兴趣爱好',
  `brief` varchar(300) DEFAULT NULL COMMENT '简介'
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=304 DEFAULT CHARSET=utf8mb4 COMMENT='会员用户';
会员等级表 member_level
CREATE TABLE `member_level` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
  `name` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '等级名称',
  `level` int(11) NOT NULL DEFAULT '0' COMMENT '等级',
  `experience` int(11) NOT NULL DEFAULT '0' COMMENT '升级经验',
  `icon` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '等级图标',
  `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态'
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='会员等级';

3、根据用户id查询排名

基于等级 level_id和经验 experience 进行排序,sql如下:

3.1、mysql 8.0以上可使用窗口函数
SELECT
    mu.id,
    mu.nickname,
    mu.avatar,
    ml.name AS level_name,
    mu.experience,
    RANK() OVER (ORDER BY ml.level DESC, mu.experience DESC) AS level_rank
FROM
    member_user mu
JOIN
    member_level ml ON mu.level_id = ml.id
WHERE
    mu.id = #{id};

解释:
1、SELECT 子句:选择我们需要的字段,包括会员 ID (member_id)、会员昵称 (member_nickname)、等级名称 (level_name)、经验 (experience),以及计算的排名 (level_rank)。
2、JOIN 语句:通过 level_id 将 member_user 表与 member_level 表连接起来。这样可以获取会员对应的等级名称和等级详细信息。
3、RANK() OVER:这是一个窗口函数,用来根据指定的排序规则对查询结果进行排名。在这里,我们首先按 level (等级) 降序排序,然后按 experience (经验) 降序排序。

以上sql没问题,可我使用的是 mysql 5.7 版本,不支持窗口函数,难道必须升级吗?升级过程出问题了咋整?好的,对症下药,多写两颗代码就搞定。
3.2、mysql 5.7 及更早版本不支持窗口函数。在这种情况下,我们可以使用子查询来实现类似的排名功能
SELECT
    mu.id,
    mu.nickname,
    mu.avatar,
    ml.name AS level_name,
    mu.experience,
    (
        SELECT COUNT(*) + 1
        FROM member_user mu2
                 JOIN member_level ml2 ON mu2.level_id = ml2.id
        WHERE (ml2.level > ml.level) OR (ml2.level = ml.level AND mu2.experience > mu.experience)
    ) AS level_rank
FROM
    member_user mu
JOIN
    member_level ml ON mu.level_id = ml.id
WHERE
    mu.id = #{id};

子查询的工作原理
1、子查询:在主查询的每一行上,子查询都会计算出比当前会员等级高或等级相同但经验更高的会员数量。
2、排名:将子查询的结果加 1 就是当前会员的排名。

总结

根据你的 MySQL 版本选择合适的解决方案。愿你大吉大利,没有bug。如果还有问题,欢迎讨论!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值