PostgreSQL中GROUP BY包含额外列的实现方案咨询
解决分组取最新记录的问题
这是个非常常见的SQL需求——按name分组后,获取每组中id最大(也就是最新)的那条完整记录,我给你几个靠谱的解决方案:
方法一:窗口函数(推荐,主流数据库支持)
如果你的数据库支持窗口函数(比如MySQL 8.0+、PostgreSQL、SQL Server、Oracle等),这是最清晰直观的写法:
SELECT id, name, company FROM ( SELECT id, name, company, -- 按name分组,每组内按id倒序排序,给每条行打序号 ROW_NUMBER() OVER (PARTITION BY name ORDER BY id DESC) AS row_num FROM users ) ranked_users -- 取每组的第一条(也就是id最大的那条) WHERE row_num = 1;
原理很简单:用PARTITION BY name把数据按name拆分成不同组,ORDER BY id DESC让每组里id最大的行排在第一位,最后筛选出序号为1的行就是你要的结果。
方法二:子查询关联(兼容老版本数据库)
如果你的数据库版本比较老(比如MySQL 5.x),不支持窗口函数,可以用子查询先找出每个name对应的最大id,再和原表关联拿到完整记录:
SELECT u.id, u.name, u.company FROM users u INNER JOIN ( -- 先分组得到每个name的最大id SELECT name, MAX(id) AS max_id FROM users GROUP BY name ) max_ids ON u.name = max_ids.name AND u.id = max_ids.max_id;
这个方法的逻辑是:先通过分组查询拿到每个name对应的最大id,再用这个结果去匹配原表,找到对应id的完整行,这样就能准确拿到对应company的值了。
方法三:LATERAL JOIN(部分数据库支持)
如果用的是PostgreSQL、SQL Server这类支持LATERAL JOIN的数据库,还可以这么写:
SELECT latest.id, latest.name, latest.company FROM (SELECT DISTINCT name FROM users) unique_names LATERAL ( -- 对每个唯一的name,取id最大的一行 SELECT id, name, company FROM users WHERE name = unique_names.name ORDER BY id DESC LIMIT 1 ) latest;
这种写法更贴近“对每个分组取最新行”的直观逻辑,先拿到所有不重复的name,再对每个name单独查询最新记录。
避坑提醒
千万别直接把company加到GROUP BY或者SELECT列表里(比如SELECT max(id), name, company FROM users GROUP BY name),除非你的数据库关闭了严格分组模式(比如MySQL的ONLY_FULL_GROUP_BY),但这么做会返回随机的company值,不是对应最大id的那个,完全不符合你的需求。
内容的提问来源于stack exchange,提问作者Stephen
相关产品推荐
相关产品推荐

