工作笔记 - PG分组极值

概述

笔者在工作的过程中,遇到一个比较典型的问题,就是需要查找分组记录中的某个极值所对应的记录。

一个经典的场景就是学生科目成绩表。分组的依据是科目。想要查询各个科目成绩最好的学生记录(假设没有并列排名)。

比较传统的方式是分组聚合(Group By) ,查到分组中的最高分,然后倒查学生记录。

还有一种方式是使用窗口函数( Rank() over ... ),找到记录在窗口中对应的排序,然后取各个窗口序号为一的那条记录。

笔者觉得这两种方式对于这个简单的需求而言,都过于繁琐。 经过和AI的讨论,发现了一种看起来比较简洁的技术方案。觉得有点意思,处理的思路也很有启发,遂著文记录和分享之。

技术方案

简单而言,这个技术方案的核心SQL是:

"Distinct ON(field)"

它可以处理重复字段值,也就是记录分组,并保留记录其他字段的值。

下面是完整的示例:

sql 复制代码
SELECT DISTINCT ON (course) stuid, course, score, examtime 
FROM scores 
ORDER BY course, score desc

// 还可以写成

SELECT DISTINCT ON (course) * FROM scores 
ORDER BY course, score desc

假设这里分组的依据是科目 course, 这个查询就可以查出分组中,按照分数倒排第一记录,当然包括学生的ID和其他其他信息。最后再对course进行汇总,就查询出所有科目的第一名学生的信息了。

简单总结一下用法:

  • distinct on () 用于指定分组的依据,所谓分组,就是字段值相同的记录的集合,它使用重复值来进行处理
  • 后面可选要提取的字段,也可以是 *
  • 关键是排序方式,因为这里的场景比较简单,就是取排序中的极值,所以先按分组排序,然后按值排序

这个查询笔者是在Postgres中调试和通过的,其他SQL系统的支持和实现情况未知。

小结

本文探讨和记录了一种不使用聚合查询和窗口函数来查询分组极值记录的一种方式。已经在笔者的一个应用中使用,觉得值得分享和探讨。

相关推荐
ss273几秒前
PostgreSQL咨询锁的使用
数据库·postgresql
ycydynq3 分钟前
django 添加信息时,对外键设置条件
数据库·python·django
Rain的Java大神之路5 分钟前
LeetCode 21 合并两个有序链表:一道 Easy 题,凭什么刷掉一半候选人?
java·后端·算法
w_t_y_y10 分钟前
JWT(5)JWT+spring security
java·后端·spring
m0_6399069420 分钟前
MySQL 索引底层原理|B + 树、聚簇索引、非聚簇索引、覆盖索引
数据库·mysql
全栈陈序员20 分钟前
【Python】基础语法入门(二十八)—— 数据库操作入门:用 SQLite 持久化数据
数据库·人工智能·python
jnrjian31 分钟前
Oracle RAC crs stop时force 关闭DB,另一个node会立即进行recover
数据库·oracle
次次皮31 分钟前
Oracle判空踩坑(对比mysql)
数据库·mysql·oracle
严谨的麻辣烫38 分钟前
固定 IP 稳定性如何检测?使用 Python 实现网络连通性与耗时监控
开发语言·数据库·php