如何让PostgreSQL窗口函数在子分组内返回相同结果?
PostgreSQL查询需求调整问题
数据表
| file | path | created |
|---|---|---|
| AAA | 08/22/A | 2022-08-22 22:00:00 |
| AAA | 08/22/A | 2022-08-22 21:00:00 |
| AAA | 08/21/A | 2022-08-21 20:00:00 |
| AAA | 08/20/A | 2022-08-20 21:00:00 |
| BBB | 08/22/B | 2022-08-22 21:00:00 |
| CCC | 08/22/C | 2022-08-22 21:00:00 |
| CCC | 08/21/C | 2022-08-21 21:00:00 |
当前查询语句
WITH ranked_messages AS ( select file, created, path, row_number() OVER (PARTITION BY file ORDER BY created DESC) AS rating_in_section from files order by file ) SELECT path FROM ranked_messages WHERE rating_in_section > 1 group by path order by path desc;
当前结果
| path |
|---|
| 08/22/A |
| 08/21/C |
| 08/21/A |
| 08/20/A |
期望结果
| path |
|---|
| 08/21/C |
| 08/21/A |
| 08/20/A |
中间状态对比
当前中间状态
| file | path | created | rating |
|---|---|---|---|
| AAA | 08/22/A | 2022-08-22 22:00:00 | 1 |
| AAA | 08/22/A | 2022-08-22 21:00:00 | 2 |
| AAA | 08/21/A | 2022-08-21 20:00:00 | 3 |
| AAA | 08/20/A | 2022-08-20 21:00:00 | 4 |
| BBB | 08/22/B | 2022-08-22 21:00:00 | 1 |
| CCC | 08/22/C | 2022-08-22 21:00:00 | 1 |
| CCC | 08/21/C | 2022-08-21 21:00:00 | 2 |
需要的中间状态
| file | path | created | rating |
|---|---|---|---|
| AAA | 08/22/A | 2022-08-22 22:00:00 | 1 |
| AAA | 08/22/A | 2022-08-22 21:00:00 | 1 |
| AAA | 08/21/A | 2022-08-21 20:00:00 | 2 |
| AAA | 08/20/A | 2022-08-20 21:00:00 | 3 |
| BBB | 08/22/B | 2022-08-22 21:00:00 | 1 |
| CCC | 08/22/C | 2022-08-22 21:00:00 | 1 |
| CCC | 08/21/C | 2022-08-21 21:00:00 | 2 |
解决方案
要实现需求,需调整窗口函数的分区逻辑,改用dense_rank()替代row_number(),让同一file下相同path的记录共享同一排名:
调整后的查询语句
WITH ranked_messages AS ( SELECT file, created, path, dense_rank() OVER (PARTITION BY file ORDER BY MAX(created) OVER (PARTITION BY file, path) DESC) AS rating_in_section FROM files ) SELECT DISTINCT path FROM ranked_messages WHERE rating_in_section > 1 ORDER BY path DESC;
逻辑说明
- 内层分区计算:
MAX(created) OVER (PARTITION BY file, path)先获取每个file+path组合的最新创建时间,确保同一path的记录拥有相同的时间标识。 - 外层排名:用
dense_rank()按file分区,以内层得到的最新时间降序排序,这样同一path的记录会被分配相同的排名。 - 筛选去重:最后筛选排名大于1的记录,通过
DISTINCT去重后得到期望结果。
内容的提问来源于stack exchange,提问作者Юрий Кот
相关产品推荐
相关产品推荐

