テーブル内のageのN番目に大きいセグメントデータをクエリーする

3628 ワード

テーブル内の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)」のデータセグメントを探して、以下の方法はすべて第2の「年齢」の行のデータを求めています.
方法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)

この方法にはバグがあり,ageが最大100に等しい場合,何行もある場合,ageの2番目に大きいデータは検索されない.そして最大のageに何行もデータがあればどうしますか?一度ずらすだけでは足りない.2番目の年齢のデータも何行もあればどうしますか?オフセット後の1行のデータだけを求めるのも明らかに間違っています.
方法2
構想:最大ageの行データを求め、whereを用いてこれらのデータ(ageMariaDB [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の同じ問題を解決した.しかし同様にとても苦痛で、ここは年齢の第2の高いデータを探して、もし第55の高いならば?ずっと反復してるの?
方法3
考え方:distinctキーワードを使用してage行を繰り返しフィルタリングし、逆ソート後のageが重複しないようにし、limit 1,1を使用して2番目の年齢のageを求め、whereを使用してage=2番目の大きいageをフィルタリングし、必要な2番目の大きい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を指す).