总结下mysql的排行榜查询,mysql 8 可以使用窗口函数,8以前就不行了。需求大概是一个游戏,用户可以玩多次,排名的时候取最高分排名

首先搞点测试数据

CREATE TABLE `t_game` (

`id` BIGINT(20) NOT NULL AUTO_INCREMENT,

`user_id` BIGINT(20) ,

`score` INT(11) ,

`create_date` DATE ,

PRIMARY KEY (`id`)

)

ENGINE = InnoDB;

INSERT INTO `t_game`(`id`, `user_id`, `score`, `create_date`)

VALUES (1, 1, 19, '2019-11-28'),

(2, 2, 96, '2019-02-09'),

(3, 3, 65, '2019-12-07'),

(4, 4, 75, '2019-09-29'),

(5, 5, 60, '2019-10-11'),

(6, 6, 8, '2019-02-03'),

(7, 7, 20, '2019-10-06'),

(8, 8, 19, '2019-09-05'),

(9, 9, 81, '2019-01-14'),

(10, 10, 75, '2019-08-26'),

(11, 1, 97, '2019-01-20'),

(12, 2, 97, '2019-02-27'),

(13, 3, 0, '2019-07-19'),

(14, 4, 73, '2019-01-06'),

(15, 5, 88, '2019-05-11'),

(16, 6, 15, '2019-09-16'),

(17, 7, 7, '2019-03-26'),

(18, 8, 95, '2019-01-21'),

(19, 9, 87, '2019-12-30'),

(20, 10, 68, '2019-06-11');

CREATE TABLE `t_user` (

`id` BIGINT(20) NOT NULL AUTO_INCREMENT,

`nickname` VARCHAR(50) ,

PRIMARY KEY (`id`)

)

ENGINE = InnoDB;

INSERT INTO `t_user`(`id`, `nickname`)

VALUES (1, '823E2A6B'),

(2, '8248806C'),

(3, '8248821D'),

(4, '824882FB'),

(5, '82488337'),

(6, '82488373'),

(7, '824883B6'),

(8, '824883E9'),

(9, '8248844F'),

(10, '82488488');

常见的排名分两种,一种是分数相同就按照提交分数的时间排名,另一种是分数相同排名就一样。

由于GROUP BY后的出的分数,不能确定是不是我们想要的最高分的那条记录,所以排名时有分两种情况。一种只看要排名对了就行,另外一种是查询出来的排名信息的每条记录上的所有字段都是正确的。

只保证关键数据正确

排名不重复

不使用开窗函数

SELECT t.*, @no := @no + 1 no

FROM (

SELECT *, max(score) maxScore

FROM t_game

GROUP BY user_id

ORDER BY maxScore DESC, id

) t,

(SELECT @no := 0) rt;

使用开窗函数

SELECT *,

max(score) maxScore,

row_number() OVER (ORDER BY max(score) DESC ) no

FROM t_game

GROUP BY user_id

查询结果

+----+---------+-------+-------------+----------+------+

| id | user_id | score | create_date | maxScore | no |

+----+---------+-------+-------------+----------+------+

| 1 | 1 | 19 | 2019-11-28 | 97 | 1 |

| 2 | 2 | 96 | 2019-02-09 | 97 | 2 |

| 8 | 8 | 19 | 2019-09-05 | 95 | 3 |

| 5 | 5 | 60 | 2019-10-11 | 88 | 4 |

| 9 | 9 | 81 | 2019-01-14 | 87 | 5 |

| 4 | 4 | 75 | 2019-09-29 | 75 | 6 |

| 10 | 10 | 75 | 2019-08-26 | 75 | 7 |

| 3 | 3 | 65 | 2019-12-07 | 65 | 8 |

| 7 | 7 | 20 | 2019-10-06 | 20 | 9 |

| 6 | 6 | 8 | 2019-02-03 | 15 | 10 |

+----+---------+-------+-------------+----------+------+

排名可重复

不使用开窗函数

SELECT t.*,

IF(@lastMaxScore = maxScore, @no, @no := @tempNo) no,

@tempNo := @tempNo + 1 tempNo,

@lastMaxScore := maxScore lastMaxScore

FROM (

SELECT *, max(score) maxScore

FROM t_game

GROUP BY user_id

ORDER BY maxScore DESC, id

) t,

(SELECT @no := 1, @lastMaxScore := 0, @tempNo := 1) rt;

使用开窗函数

SELECT *,

max(score) maxScore,

rank() OVER (ORDER BY max(score) DESC ) no

FROM t_game

GROUP BY user_id

查询结果

+----+---------+-------+-------------+----------+------+

| id | user_id | score | create_date | maxScore | no |

+----+---------+-------+-------------+----------+------+

| 1 | 1 | 19 | 2019-11-28 | 97 | 1 |

| 2 | 2 | 96 | 2019-02-09 | 97 | 1 |

| 8 | 8 | 19 | 2019-09-05 | 95 | 3 |

| 5 | 5 | 60 | 2019-10-11 | 88 | 4 |

| 9 | 9 | 81 | 2019-01-14 | 87 | 5 |

| 4 | 4 | 75 | 2019-09-29 | 75 | 6 |

| 10 | 10 | 75 | 2019-08-26 | 75 | 6 |

| 3 | 3 | 65 | 2019-12-07 | 65 | 8 |

| 7 | 7 | 20 | 2019-10-06 | 20 | 9 |

| 6 | 6 | 8 | 2019-02-03 | 15 | 10 |

+----+---------+-------+-------------+----------+------+

保证所有数据正确

排名不重复

不使用开窗函数

SELECT id, user_id, score, create_date, @no := @no + 1 no

FROM (

SELECT *, IF(@tmp <> user_id, @i := 1, @i := @i + 1) i, @tmp := user_id

FROM (

SELECT *

FROM t_game

ORDER BY user_id, score DESC, id

) t,

(SELECT @i := 0, @tmp := NULL) it

) t1,

(SELECT @no := 0) rt

WHERE i = 1

ORDER BY score DESC, t1.id

使用开窗函数

SELECT id, user_id, score, create_date, row_number() OVER (ORDER BY score DESC) no

FROM (

SELECT *, row_number() OVER (PARTITION BY user_id ORDER BY score DESC) i

FROM t_game

) t

WHERE i = 1

查询结果

+----+---------+-------+-------------+----+

| 11 | 1 | 97 | 2019-01-20 | 1 |

| 12 | 2 | 97 | 2019-02-27 | 2 |

| 18 | 8 | 95 | 2019-01-21 | 3 |

| 15 | 5 | 88 | 2019-05-11 | 4 |

| 19 | 9 | 87 | 2019-12-30 | 5 |

| 4 | 4 | 75 | 2019-09-29 | 6 |

| 10 | 10 | 75 | 2019-08-26 | 7 |

| 3 | 3 | 65 | 2019-12-07 | 8 |

| 7 | 7 | 20 | 2019-10-06 | 9 |

| 16 | 6 | 15 | 2019-09-16 | 10 |

+----+---------+-------+-------------+----+

排名可重复

不使用开窗函数

SELECT id,

user_id,

score,

create_date,

IF(@lastScore = score, @no, @no := @tempNo) no,

@tempNo := @tempNo + 1 tempNo,

@lastScore := score lastScore

FROM (

SELECT *, IF(@tmp <> user_id, @i := 1, @i := @i + 1) i, @tmp := user_id

FROM (

SELECT *

FROM t_game

ORDER BY user_id, score DESC, id

) t,

(SELECT @i := 0, @tmp := NULL) it

) t1,

(SELECT @no := 1, @lastScore := 0, @tempNo := 1) rt

WHERE i = 1

ORDER BY score DESC, t1.id;

使用开窗函数

SELECT id,

user_id,

score,

create_date,

rank() OVER (ORDER BY score DESC) no

FROM (

SELECT *, row_number() OVER (PARTITION BY user_id ORDER BY score DESC) i

FROM t_game

) t

WHERE i = 1

查询结果

+----+---------+-------+-------------+----+

| id | user_id | score | create_date | no |

+----+---------+-------+-------------+----+

| 11 | 1 | 97 | 2019-01-20 | 1 |

| 12 | 2 | 97 | 2019-02-27 | 1 |

| 18 | 8 | 95 | 2019-01-21 | 3 |

| 15 | 5 | 88 | 2019-05-11 | 4 |

| 19 | 9 | 87 | 2019-12-30 | 5 |

| 4 | 4 | 75 | 2019-09-29 | 6 |

| 10 | 10 | 75 | 2019-08-26 | 6 |

| 3 | 3 | 65 | 2019-12-07 | 8 |

| 7 | 7 | 20 | 2019-10-06 | 9 |

| 16 | 6 | 15 | 2019-09-16 | 10 |

+----+---------+-------+-------------+----+

mysql 查排行榜_mysql 查询排行榜相关推荐

  1. mysql查姓_mysql查询

    -- 10.21   SQL练习 -- 表结构和数据参见4个.sql文件 -- 1.查询"c001"课程比"c002"课程成绩高的所有学生的学号: select ...

  2. mysql 严格区分大小写_Mysql查询英文如何严格区分大小写?

    1. 前提: 在Mysql数据库中进行查询时,希望英文严格区分大小写.默认情况下是不区分大小写的. 2. 演示如下: 在数据库表emp中,job字段中存储的值有'Engineer',现在的情况是,下面 ...

  3. 在mysql中通配符_mysql查询中通配符的使用

    mysql查询中通配符的使用 在mysql查询中经常会使用通配符,并且mysql的通配符和pgsql的存在区别(稍候再讨论),而且mysql中还可以使用正则表达式. SQL模式匹配: "_& ...

  4. mysql 查阻塞_mysql检查阻塞进程

    前言:朋友咨询我说执行简单的update语句失效,症状如下: mysql> update order_info set province_id=15 ,city_id= 1667 where o ...

  5. mysql制作排行榜_mysql实现排行榜

    博主新人一枚,大家可以提出自己的宝贵意见. 下来我们进入正题. 前两天在给app写接口时,需要实现一个排行榜的业务.当然我们首先要了解排行榜的业务需求是什么,其次才是接口实现,不能像我一样,走了不少的 ...

  6. mysql游戏名称_MySQL 游戏排行榜

    今天在坛子上看到了,顺便写下来. 有两种方法: 1.效率不高,因为有子查询.但是简洁.而且我对SOCRES表做了INDEX.所以性能上也差不了多少. mysql> show create tab ...

  7. mysql 前索引_MySQL查询性能优化前,必须先掌握MySQL索引理论

    数据库索引在平时的工作是必备的,怎么建好索引,怎么使用索引,可以提高数据的查询效率.而且在面试过程,数据库的索引也是必问的知识点,比如: 索引底层结构选型,那为什么选择B+树? 不同存储引擎的索引的体 ...

  8. mysql in操作_MySQL查询in操作排序

    in操作排序 先说解决方案: select * from test where id in(3,1,5) order by field(id,3,1,5); 或许有人会注意过,但我以前真不知道 SQL ...

  9. mysql 性能查看_MySQL查询性能问题排查

    Mysql数据库的性能问题排查是十分复杂的,具体方法视场景而定,这里只做大致思路分析. 1. 整体考虑导致查询性能低下的各种因素 导致SQL查询变慢的原因是多元化的,在遇到问题时首先要有一个全方位的思 ...

最新文章

  1. 基于EMQ X,打造AIoT物联网视频接入解决方案
  2. 【智能语音】ROC-RK3308-CC Amazon Alexa固件发布
  3. 微信小程序ios可以上下左右拖动的问题
  4. 软件工程--团队作业4
  5. Fragment回调Activity的事件分发
  6. noip2016 组合数问题
  7. kaggle (02) - 房价预测案例(进阶版)
  8. 从KPI到OKR,高阶产品人如何推动业务高速增长
  9. 信息系统项目管理师 高级 论文备考专题 老师现场写论文
  10. 【1131】C/C++经典程序训练1---最大公约数与最小公倍数
  11. Cisco dynamips模拟器安装指南
  12. mysql2008安装失败_sql server 2008为什么会安装失败 sql2008安装失败解决办法
  13. 关于vue使用print.js打印会有一个空白页的问题
  14. 计算机国内外SCI/EI收录期刊一览(参考)
  15. php 实现游戏开发
  16. 程序员笔试题收集汇总(三)
  17. 使用docker安装mysql8及mysql5.7
  18. 安卓App生成签名证书,uniapp生成自有证书打包
  19. c语言API用法 查询
  20. KVM+WebVirtMgr部署安装笔记

热门文章

  1. windows删除多余启动引导项
  2. POJ2255二叉树
  3. zzulioj 1052
  4. c++ 繁体中文与简体中文的转换
  5. 2019-12 前端技术汇总
  6. win系统压缩/解压.tar.gz 文件的方法
  7. 【NLP模型笔记】Intro || Word2vec词向量模型
  8. 百度墨卡托投影坐标转WGS84
  9. 机器人轴配置数据详解
  10. L2-031 深入虎穴 (25 分)(DFS 代码有详细解析)