如何通过PostgreSQL窗口函数简化复杂自连接查询,增强代码易读性?
- 内容介绍
- 文章标签
- 相关推荐
本文共计660个文字,预计阅读时间需要3分钟。
由于自连接依赖JOIN条件的完整性及准确性,遗漏了一个AND e2.salary。
查每个部门工资最高的员工:别用LEFT JOIN子查询
常见错误是写两层嵌套子查询找max(salary),再JOIN回来匹配——既难读又慢。直接用ROW_NUMBER()压平逻辑:
SELECT dept_id, name, salary FROM ( SELECT dept_id, name, salary, ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY salary DESC, id) AS rn FROM employees ) t WHERE rn = 1;
-
PARTITION BY dept_id确保每组独立编号 -
ORDER BY salary DESC, id解决同薪并列时序号不确定问题(id兜底) - 必须加
id或其它唯一字段,否则PostgreSQL可能每次返回不同员工 - 如果允许并列第一,换用
RANK(),但要注意WHERE rn = 1仍能命中所有并列者
算用户连续登录天数:LAG()比自连接少写8行
传统做法是自连接ON u1.user_id = u2.user_id AND u2.login_date = u1.login_date + INTERVAL '1 day',再GROUP BY用户+日期差做断点识别。
本文共计660个文字,预计阅读时间需要3分钟。
由于自连接依赖JOIN条件的完整性及准确性,遗漏了一个AND e2.salary。
查每个部门工资最高的员工:别用LEFT JOIN子查询
常见错误是写两层嵌套子查询找max(salary),再JOIN回来匹配——既难读又慢。直接用ROW_NUMBER()压平逻辑:
SELECT dept_id, name, salary FROM ( SELECT dept_id, name, salary, ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY salary DESC, id) AS rn FROM employees ) t WHERE rn = 1;
-
PARTITION BY dept_id确保每组独立编号 -
ORDER BY salary DESC, id解决同薪并列时序号不确定问题(id兜底) - 必须加
id或其它唯一字段,否则PostgreSQL可能每次返回不同员工 - 如果允许并列第一,换用
RANK(),但要注意WHERE rn = 1仍能命中所有并列者
算用户连续登录天数:LAG()比自连接少写8行
传统做法是自连接ON u1.user_id = u2.user_id AND u2.login_date = u1.login_date + INTERVAL '1 day',再GROUP BY用户+日期差做断点识别。

