工作笔记 - 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系统的支持和实现情况未知。

小结

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

相关推荐
一条泥憨鱼2 分钟前
苍穹外卖【day10| 来电提醒和客户催单】
java·后端·websocket·苍穹外卖
ly768912 分钟前
Spring Boot 3.2 虚拟线程在 Web 层与 JDBC 池的实践边界
前端·spring boot·后端·tomcat·jdbc·虚拟线程
聚美智数16 分钟前
车辆合格证OCR识别-机动车合格证识别-车辆合格证OCR‑机动车出厂证解析‑整车参数提取 API 接口介绍
数据库·经验分享
DBA_G19 分钟前
南大通用技术分享:GBase 8a数据库执行计划架构原理解析
数据库
盖伦发发24 分钟前
SpringCloud Alibaba Sentinel 教学:限流、熔断、降级、线程/信号量隔离、活动过载保护
后端·软件工程
QQ_216962909627 分钟前
基于SpringBoot+Vue的小生活平台的设计与实现
java·数据库·vue.js·spring boot·spring·微信小程序·生活
考虑考虑8 小时前
数据库中的EXISTS
运维·数据库·后端
Wang's Blog9 小时前
Java框架快速入门: Spring Security+OAuth2之数据库和实体类的RBAC改造
java·数据库·spring
郑州光合科技余经理9 小时前
国际版外卖系统:税率字段怎么和订单主流程解耦
android·java·开发语言·前端·后端·php·ai编程
毅炼9 小时前
Rover-Suite 开源发布:轻量服务注册中心与网关一体化方案
java·后端·系统架构·gateway