如何在低版本Firebird中实现带PARTITION BY的ROW_NUMBER类似功能?
模拟Firebird旧版本中带PARTITION BY的ROW_NUMBER功能
针对你在遗留政务系统里无法升级Firebird版本,需要按id_exercicio分区生成序号的需求,你之前用rdb$set_context的方式只能生成全局连续序号,没法实现分区重置。这里可以用关联子查询的方式来模拟PARTITION BY id_exercicio的效果:
解决方案代码
SELECT (SELECT COUNT(*) FROM LICITACAO_PROCESSO lp_inner WHERE lp_inner.id_exercicio = lp_outer.id_exercicio AND (lp_inner.ID_MODALIDADE < lp_outer.ID_MODALIDADE OR (lp_inner.ID_MODALIDADE = lp_outer.ID_MODALIDADE AND lp_inner.id_exercicio = lp_outer.id_exercicio) ) ) AS seq, lp_outer.id_exercicio, lp_outer.ID_MODALIDADE FROM LICITACAO_PROCESSO lp_outer GROUP BY lp_outer.id_exercicio, lp_outer.ID_MODALIDADE ORDER BY lp_outer.id_exercicio, lp_outer.ID_MODALIDADE;
思路说明
- 核心逻辑是通过关联子查询,针对每一行数据,统计同一
id_exercicio分区内,排序字段(这里是ID_MODALIDADE)小于等于当前行的记录数,以此来模拟分区内的序号递增。 - 如果你需要按其他字段排序,只需要调整子查询里的排序条件即可(比如如果表有主键,用主键来判断顺序能避免重复序号的问题,会更准确)。
- 这种方式不需要依赖事务上下文变量,完全基于表内数据的关联来实现分区计数,刚好匹配你需要的
PARTITION BY效果。
另外补充:如果你的LICITACAO_PROCESSO表在id_exercicio和ID_MODALIDADE上有索引的话,这个查询的性能会提升很多,建议检查下索引配置哦。
内容的提问来源于stack exchange,提问作者Diego Alves
相关产品推荐
相关产品推荐

