PostgreSQL按uuid去重并按start排序的实现方案咨询
问题原因与解决方案
错误原因
PostgreSQL 的 DISTINCT ON 语法有硬性要求:ORDER BY 子句的第一个字段必须和 DISTINCT ON 指定的字段完全一致。你原SQL中仅按 events.start 排序,违反了这个规则,导致报错。
可行解决方案
方案一:嵌套子查询 + DISTINCT ON
先通过 DISTINCT ON 按 events.uuid 去重,再在外层按 events.start 排序最终结果:
SELECT nickname, id FROM ( SELECT DISTINCT ON (events.uuid) events.nickname, plays.id, events.start FROM events JOIN plays ON plays.eventuuid = events.uuid -- 内层必须先按DISTINCT ON的字段排序,再按start确定分组内保留的记录 ORDER BY events.uuid, events.start ) AS sub_query -- 外层按start排序整个结果集 ORDER BY start;
方案二:窗口函数 ROW_NUMBER()
用窗口函数给每个 events.uuid 分组的记录编号,筛选出每组第一条后再排序,逻辑更灵活:
SELECT nickname, id FROM ( SELECT events.nickname, plays.id, events.start, -- 按uuid分组,按start排序,给每组记录编序号 ROW_NUMBER() OVER (PARTITION BY events.uuid ORDER BY events.start) AS row_num FROM events JOIN plays ON plays.eventuuid = events.uuid ) AS sub_query -- 取每组的第一条记录 WHERE row_num = 1 -- 最终按start排序 ORDER BY start;
如果需要每个event对应特定的play(比如最新创建的play),可以修改窗口函数的排序规则,例如:
ROW_NUMBER() OVER (PARTITION BY events.uuid ORDER BY events.start, plays.created_at DESC) AS row_num
内容的提问来源于stack exchange,提问作者Joymaker
相关产品推荐
相关产品推荐

