PostgreSQL实现按交易ID分组并按指定规则排序结果的方法
交易记录排序的SQL实现方案
表结构
| id | transaction_id | status | created_at | updated_at |
|---|---|---|---|---|
| uuid-1 | a293b1fe0369e0198df3293a8aef9c97ea532b30 | completed | 2022-08-25 02:32:44 | 2022-08-25 02:32:44 |
| uuid-2 | a293b1fe0369e0198df3293a8aef9c97ea532b24 | failed | 2022-08-24 12:33:22 | 2022-08-24 12:33:22 |
| uuid-3 | 3b97c805fc7ce00119433c5284102b47781f9f66 | pending | 2022-08-24 12:30:22 | 2022-08-24 12:33:22 |
| uuid-4 | a293b1fe0369e0198df3293a8aef9c97ea532b30 | failed | 2022-08-23 9:32:14 | 2022-08-23 9:32:14 |
| uuid-5 | a293b1fe0369e0198df3293a8aef9c97ea532b30 | failed | 2022-08-05 9:22:34 | 2022-08-05 9:22:34 |
| uuid-6 | a293b1fe0369e0198df3293a8aef9c97ea532b24 | pending | 2022-08-04 03:33:12 | 2022-08-04 03:33:12 |
| uuid-7 | a293b1fe0369e0198df3293a8aef9c97ea532b30 | failed | 2022-08-01 4:04:25 | 2022-08-01 4:04:25 |
| uuid-8 | a293b1fe0369e0198df3293a8aef9c97ea532b30 | pending | 2022-07-20 7:43:22 | 2022-07-20 7:43:22 |
排序规则
- 最新提交的交易排在最顶部(按每个交易组的最晚创建时间倒序排列)
- 每个交易下的操作记录按指定状态顺序排序:
pending→failed→completed,同状态下按创建时间正序排列
期望结果
| transaction_id | status | created_at | updated_at |
|---|---|---|---|
| 3b97c805fc7ce00119433c5284102b47781f9f66 | pending | 2022-08-24 12:30:22 | 2022-08-24 12:33:22 |
| a293b1fe0369e0198df3293a8aef9c97ea532b24 | pending | 2022-08-04 03:33:12 | 2022-08-04 03:33:12 |
| a293b1fe0369e0198df3293a8aef9c97ea532b24 | failed | 2022-08-24 12:33:22 | 2022-08-24 12:33:22 |
| a293b1fe0369e0198df3293a8aef9c97ea532b30 | pending | 2022-07-20 7:43:22 | 2022-07-20 7:43:22 |
| a293b1fe0369e0198df3293a8aef9c97ea532b30 | failed | 2022-08-01 4:04:25 | 2022-08-01 4:04:25 |
| a293b1fe0369e0198df3293a8aef9c97ea532b30 | failed | 2022-08-05 9:22:34 | 2022-08-05 9:22:34 |
| a293b1fe0369e0198df3293a8aef9c97ea532b30 | failed | 2022-08-23 9:32:14 | 2022-08-23 9:32:14 |
| a293b1fe0369e0198df3293a8aef9c97ea532b30 | completed | 2022-08-25 02:32:44 | 2022-08-25 02:32:44 |
尝试的SQL
select transaction_id, created_at, status, RANK() over (partition by transaction_id order by created_at) group_rank from transactions;
解决方案
要实现需求,需要同时处理交易组的排序和组内记录的排序,最终SQL如下:
select transaction_id, status, created_at, updated_at from ( select transaction_id, status, created_at, updated_at, -- 获取每个交易组的最晚创建时间,用于交易组排序 max(created_at) over (partition by transaction_id) as latest_transaction_time, -- 为状态分配自定义排序优先级 case status when 'pending' then 1 when 'failed' then 2 when 'completed' then 3 end as status_order from transactions ) t -- 按规则排序:交易组最新时间倒序 → 状态优先级正序 → 创建时间正序 order by latest_transaction_time desc, status_order asc, created_at asc;
逻辑说明
- 交易组排序:通过
max(created_at) over (partition by transaction_id)计算每个交易的最晚提交时间,以此作为组的排序依据,确保最新提交的交易排在最前 - 组内状态排序:用
case语句给每个状态分配排序值,实现pending→failed→completed的指定顺序 - 同状态排序:同状态下按
created_at正序排列,符合创建顺序要求
内容的提问来源于stack exchange,提问作者Dyapa Srikanth
相关产品推荐
相关产品推荐

