首页 > 解决方案 > 在 MySQL 8 中按类别显示前 N 行,在另一个类别中没有重复

问题描述

此问题类似,我在 MySQL 8.0.15 中有下表:

CREATE TABLE golf_scores (id INT PRIMARY KEY AUTO_INCREMENT, person TEXT, score INT, age INT);
INSERT INTO golf_scores (person, score, age) VALUES ('Angela', 40, 25),('Angela', 45, 25),('Angela', 55, 25),('Peter',45, 32),('Peter',55,32),('Rachel', 65, 35),('Rachel',75,35),('Jeff',75, 16);
SELECT * FROM golf_scores;
+----+--------+-------+------+
| id | person | score | age  |
+----+--------+-------+------+
|  1 | Angela |    40 |   25 |
|  2 | Angela |    45 |   25 |
|  3 | Angela |    55 |   25 |
|  4 | Peter  |    45 |   32 |
|  5 | Peter  |    55 |   32 |
|  6 | Rachel |    65 |   35 |
|  7 | Rachel |    75 |   35 |
|  8 | Jeff   |    75 |   16 |
+----+--------+-------+------+

我们要选择以下“最佳”3 行:

+----+--------+-------+------+
| id | person | score | age  |
+----+--------+-------+------+
|  1 | Angela |    40 |   25 |
|  4 | Peter  |    45 |   32 |
|  6 | Rachel |    65 |   35 |
+----+--------+-------+------+

换句话说,最低的 3 个高尔夫球得分没有人重复,以及该行的其他列。我不担心关系;我仍然想要三个结果。

查询SELECT person, MIN(score) as min_score FROM golf_scores GROUP BY person ORDER BY min_score LIMIT 3;给出了正确的行,但仅限于列person和分数。当我尝试像这样修改它时:

SELECT id, person, MIN(score) as min_score, age FROM golf_scores GROUP BY person ORDER BY min_score LIMIT 3;

我收到此错误:

错误 1055 (42000):SELECT 列表的表达式 #1 不在 GROUP BY 子句中,并且包含在功能上不依赖于 GROUP BY 子句中的列的非聚合列“records.golf_scores.id”;这与 sql_mode=only_full_group_by 不兼容

我也尝试过消除重复名称,SELECT id, DISTINCT person, score, age FROM golf_scores ORDER BY score LIMIT 3但出现错误

ERROR 1064 (42000):您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在第 1 行的“DISTINCT person, score FROM golf_scores ORDER BY score LIMIT 3”附近使用正确的语法

如何在 MySQL 中获得所需的输出?

标签: mysqlsqlgroup-bydistinctmysql-8.0

解决方案


使用row_number()

select t.*
from (select t.*, row_number() over (partition by person order by score) as seqnum
      from golf_scores  t
     ) t
where seqnum = 1
order by score asc
limit 3;

在旧版本中,您可以通过使用相关子查询来做到这一点,并且id

select gs.*
from golf_scores gs
where gs.id = (select gs2.id
               from golf_scores gs2
               where gs2.person = gs.person
               order by gs2.score asc
               limit 1
              )
order by score asc
limit 3;

这也可能是索引 on 的最快方式golf_scores(person, score, id)


推荐阅读