Firebird 2.5多表查询优化:获取NUMEROCOMMESSA最大REVISIONE行
解决Firebird 2.5中按NUMEROCOMMESSA取最大REVISIONE唯一行的问题
你遇到的重复数据问题,根源是同一个NUMEROCOMMESSA对应了多个REVISIONE值,而原查询没有筛选出每个订单号对应的最新(最大)版本行。Firebird 2.5支持窗口函数,这是处理这类分组取最值场景最优雅的方案。
优化后的查询语句
WITH ranked_produzione AS ( SELECT PRODUZIONE_T.CODPRODUZIONE, PRODUZIONE_T.NUMEROCOMMESSA AS numeroco, ANGCLIENTIFORNITORI.RAGIONESOCIALE1, PRODUZIONE_T.DATACONSEGNA, PRODUZIONE_T.REVISIONE, ANGUTENTI.NOMINATIVO, ORDINI_T.T_DATA, -- 按NUMEROCOMMESSA分组,每组内按REVISIONE降序编号,最大版本号得1 ROW_NUMBER() OVER (PARTITION BY PRODUZIONE_T.NUMEROCOMMESSA ORDER BY PRODUZIONE_T.REVISIONE DESC) AS rn FROM PRODUZIONE_T LEFT OUTER JOIN ORDINI_T ON PRODUZIONE_T.CODORDINE = ORDINI_T.CODORDINE INNER JOIN ANGCLIENTIFORNITORI ON ANGCLIENTIFORNITORI.CODCLIFOR = ORDINI_T.CODCLIFOR LEFT OUTER JOIN ANGUTENTI ON ANGUTENTI.IDUTENTE = PRODUZIONE_T.RESPONSABILEUC ) SELECT CODPRODUZIONE, numeroco, RAGIONESOCIALE1, DATACONSEGNA, REVISIONE, NOMINATIVO, T_DATA FROM ranked_produzione WHERE rn = 1 -- 只保留每组中版本号最大的行 ORDER BY RIGHT(numeroco,2) DESC, LEFT(numeroco,3) DESC ROWS 1 TO 500;
关键逻辑说明
- CTE(公共表表达式)
ranked_produzione:先执行原查询的表关联逻辑,同时用ROW_NUMBER()窗口函数给每个NUMEROCOMMESSA分组内的行编号。PARTITION BY PRODUZIONE_T.NUMEROCOMMESSA确保每个订单号单独分组,ORDER BY PRODUZIONE_T.REVISIONE DESC让最大的版本号排在每组的第一位,对应行号rn=1。 - 外层筛选:通过
WHERE rn = 1过滤掉每个分组中版本号不是最大的行,只保留唯一的最新版本行。
备选方案(关联子查询)
如果你更习惯用传统的关联方式,也可以通过子查询先找到每个NUMEROCOMMESSA的最大REVISIONE,再关联回主查询:
SELECT P.CODPRODUZIONE, P.NUMEROCOMMESSA AS numeroco, A.RAGIONESOCIALE1, P.DATACONSEGNA, P.REVISIONE, U.NOMINATIVO, O.T_DATA FROM PRODUZIONE_T P LEFT OUTER JOIN ORDINI_T O ON P.CODORDINE = O.CODORDINE INNER JOIN ANGCLIENTIFORNITORI A ON A.CODCLIFOR = O.CODCLIFOR LEFT OUTER JOIN ANGUTENTI U ON U.IDUTENTE = P.RESPONSABILEUC -- 关联子查询获取当前NUMEROCOMMESSA的最大REVISIONE INNER JOIN ( SELECT NUMEROCOMMESSA, MAX(REVISIONE) AS MAX_REV FROM PRODUZIONE_T GROUP BY NUMEROCOMMESSA ) PR ON P.NUMEROCOMMESSA = PR.NUMEROCOMMESSA AND P.REVISIONE = PR.MAX_REV ORDER BY RIGHT(numeroco,2) DESC, LEFT(numeroco,3) DESC ROWS 1 TO 500;
不过窗口函数的方案在性能上更优,尤其是当数据量较大时,因为它只需要扫描一次表,而关联子查询可能需要多次扫描。
内容的提问来源于stack exchange,提问作者Massimo Griffani
相关产品推荐
相关产品推荐

