分组后查找每组的前N条记录

本文介绍了一种使用SQL语句从数据库中选取每个班级前两名学生的技巧。通过子查询计数每组内小于当前ID的记录数量,筛选出符合条件的学生信息,并按班级和ID排序。
部署运行你感兴趣的模型镜像

今天,一个同学的问我一条问题,具体如下:

 

 

为了测试,我建立了一个表,叫student,并添加了N条数据:

 

 

最终预期结果应该是:

 

 

根据题意是,按class分组,然后取id靠前的两名,相信大多数人都能想到基本组合:

SELECT a.*

FROM student a

ORDER BY a.class, a.id;

另加:Limit 0,2来配合。

 

(注:MYSQL 中没有top n的写法,取代的是LIMIT。)

Limit 0,n只能取到最前的n位,但如何能取到每个班的前两位呢,就无从下手了。

 

下面我来具体分析一下这题的解法:

1、获取每个class的前两位:

SELECT a.*

FROM student a

WHERE

(

  SELECT COUNT(*)

  FROM student

  WHERE class = a.class

  AND id < a.id

) < 2

 

#遍历所有记录,然后取该条记录与同班中的所有记录比较,只有当班上不超过两个人(含两个人)比该记录id小的话,该记录才被认定为该记录id排名前2,然后显示出来。

 

2、当获取所有合格的数据有,按class与id排序:

在最后添加:

ORDER BY a.class, a.id;

 

最终结果:

SELECT a. *
FROM student a
WHERE (

SELECT COUNT( * )
FROM student
WHERE class = a.class
AND id < a.id
) <2
ORDER BY a.class, a.id
LIMIT 0 , 30;

 

 

您可能感兴趣的与本文相关的镜像

Anything-LLM

Anything-LLM

AI应用

AnythingLLM是一个全栈应用程序,可以使用商用或开源的LLM/嵌入器/语义向量数据库模型,帮助用户在本地或云端搭建个性化的聊天机器人系统,且无需复杂设置

### 使用窗口函数实现分组N记录MySQL 8.0 及以上版本中,可以使用窗口函数 `ROW_NUMBER()` 来实现分组后获取每组 N 记录。以下是一个示例查询: ```sql WITH ranked_data AS ( SELECT group_id, record_id, created_at, ROW_NUMBER() OVER (PARTITION BY group_id ORDER BY created_at DESC) AS row_num FROM your_table ) SELECT group_id, record_id, created_at FROM ranked_data WHERE row_num <= N; ``` 在这个查询中: - `PARTITION BY group_id` 表示按 `group_id` 分组。 - `ORDER BY created_at DESC` 表示每组数据按时间降序排列。 - `ROW_NUMBER()` 为每记录分配一个行号。 - 最终通过 `row_num <= N` 获取每组 N 记录 [^1]。 ### 不使用窗口函数(适用于 MySQL 5.x) 在不支持窗口函数的 MySQL 版本中,可以通过子查询和自连接来实现类似效果。例如: ```sql SELECT t1.group_id, t1.record_id, t1.created_at FROM your_table t1 LEFT JOIN your_table t2 ON t1.group_id = t2.group_id AND t1.created_at < t2.created_at GROUP BY t1.group_id, t1.record_id, t1.created_at HAVING COUNT(t2.record_id) < N; ``` 该查询的核心思想是:对于每记录 `t1`,查找同组中比它更新的记录 `t2` 的数量。如果数量小于 N,则表示它是该组的 N 记录之一 [^3]。 ### 示例说明 假设表 `your_table` 包含如下数据: | group_id | record_id | created_at | |----------|-----------|---------------------| | 1 | 101 | 2023-01-01 10:00:00 | | 1 | 102 | 2023-01-02 10:00:00 | | 1 | 103 | 2023-01-03 10:00:00 | | 2 | 104 | 2023-01-01 10:00:00 | | 2 | 105 | 2023-01-02 10:00:00 | 执行上述查询后,结果将获取每组中 `created_at` 最新的 N 记录: | group_id | record_id | created_at | |----------|-----------|---------------------| | 1 | 102 | 2023-01-02 10:00:00 | | 1 | 103 | 2023-01-03 10:00:00 | | 2 | 104 | 2023-01-01 10:00:00 | | 2 | 105 | 2023-01-02 10:00:00 | ### 注意事项 - 如果存在多记录具有相同的最大时间值(即并列最新),则需要考虑是否要全部保留或仅保留。 - 在性能方面,建议对 `group_id` 和 `created_at` 字段建立复合索引以加速查询 [^2]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值