查询一个表中如age第N大的段数据

查询一个表中如age第N大的段数据

测试表:

MariaDB [jinyong]> show tables;
+-------------------+
| Tables_in_jinyong |
+-------------------+
| user              |
+-------------------+
1 row in set (0.01 sec)
​
MariaDB [jinyong]> desc user;
+-------+--------------------+------+-----+---------+----------------+
| Field | Type               | Null | Key | Default | Extra          |
+-------+--------------------+------+-----+---------+----------------+
| id    | int(11)            | NO   | PRI | NULL    | auto_increment |
| name  | varchar(20)        | NO   |     | NULL    |                |
| age   | tinyint(4)         | NO   |     | NULL    |                |
| sex   | enum('girl','boy') | YES  |     | NULL    |                |
| skill | varchar(20)        | NO   |     | NULL    |                |
| time  | time               | YES  |     | NULL    |                |
+-------+--------------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
//表中有六个字段,且有1061行数据,这里无法全部显示。其中age表示年龄为tinyint类型

下面介绍本人可以想到的一些拙劣的办法去查找第N大"年龄(age)"的数据段,下面方法都是在求第"二"大年龄的行数据。

方法1

方法思路:对数据以年龄进行倒排序,然后使用limit求第一个偏移量后一行数据。

MariaDB [jinyong]> select * from user order by age desc limit 1,1;
+------+------+-----+------+---------------+----------+
| id   | name | age | sex  | skill         | time     |
+------+------+-----+------+---------------+----------+
| 2794 | qTz  | 100 | boy  | J九阴真经     | 18:01:03 |
+------+------+-----+------+---------------+----------+
1 row in set (0.00 sec)

这种方法有bug,如果age最大等于100时,有好几行,则查找出来的不是age第二大的数据。而且如果最大的age有好几行数据怎么办?偏移一次是不够的。如果年龄第二大的数据也有好几行怎么办?只求偏移后一行数据显然也是不对的。

方法2

思路:求出最大age的行数据,使用where过滤掉这些数据(age < max(age)),然后再求出这样的最大的age(就是原本数据的第二大age),最后使用where age =max2(age)求出这样的数据。

MariaDB [jinyong]> select * from user where age = (select MAX(age) from user where age < (select max(age) from user ORDER BY age desc));
+------+------+-----+------+------------------+----------+
| id   | name | age | sex  | skill            | time     |
+------+------+-----+------+------------------+----------+
| 2412 | Cyo  |  99 | girl | D打狗棍法        | 18:00:23 |
| 2705 | YGa  |  99 | boy  | J九阴真经        | 18:01:01 |
| 2754 | VMh  |  99 | girl | D打狗棍法        | 18:01:02 |
| 2774 | WGR  |  99 | girl | X降龙十八掌      | 18:01:02 |
+------+------+-----+------+------------------+----------+
4 rows in set (0.00 sec)

这种方法解决了多行age相同的问题。但是同样也很痛苦,这里让找年龄第二高的数据,如果是第55高的呢?难道一直迭代?

方法3

思路:使用distinct关键字将age行重复的过滤掉,这样倒排序后的age就不会有重复,然后使用limit 1,1求出第二大年龄的age,再使用一次where过滤出age=第二大的age,即求出需要的第二大age的所有数据。

​
MariaDB [jinyong]> select * from user where age =(select distinct age from user order by age desc limit 1,1); 
+------+------+-----+------+------------------+----------+
| id   | name | age | sex  | skill            | time     |
+------+------+-----+------+------------------+----------+
| 2412 | Cyo  |  99 | girl | D打狗棍法        | 18:00:23 |
| 2705 | YGa  |  99 | boy  | J九阴真经        | 18:01:01 |
| 2754 | VMh  |  99 | girl | D打狗棍法        | 18:01:02 |
| 2774 | WGR  |  99 | girl | X降龙十八掌      | 18:01:02 |
+------+------+-----+------+------------------+----------+
4 rows in set (0.00 sec)

这种方法不但解决了方法1中如果有重复age的问题(distinct关键字),而且还避免了不停迭代的痛苦(distinct除去冗余后limit的偏移量和偏移后的行数都是绝对指向所求的age)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值