旧式逗号关联SQL改写为JOIN语法后结果不一致,求助错误位置
SQL改写错误排查及修正方案
- 首先确认老语法的语义匹配问题
你用的*=、=*是老式数据库的外连接语法,不同厂商实现存在差异:- 如果你用的是老版本SQL Server:
*=等价于左外连接、=*等价于右外连接,这部分你的改写语义是对的 - 如果你用的是Informix等其他数据库:
*在等号哪一侧就代表哪一侧的表允许为空,和SQL Server语义完全相反,你需要把对应外连接的方向反转
- 如果你用的是老版本SQL Server:
- 其次是JOIN顺序导致的结果差异
你原写法的JOIN顺序不合理:将2个关联CI_CLIENTE的内连接(CI_CLIENTE_SGTO_CANAL、CI_DIRECCIONES)放在了4个左连接之后,部分老优化器会因为JOIN顺序的不同,在左连接产生重复行后再做内连接,导致计数结果和原查询不一致。
修正后的改写版本如下,将所有内连接统一前置,再处理左连接,保证和原查询的过滤优先级一致:
select count(*) from CI_PRODUCTO join CI_PROD_CAT on CI_PRODUCTO.swProdReleaseId=CI_PROD_CAT.swProdReleaseId join CI_CLIENTE on CI_PRODUCTO.swCustomerId=CI_CLIENTE.swCustomerId join CI_CONTRATO on CI_CONTRATO.swAgreementId=CI_PRODUCTO.swAgreementId -- 所有内连接前置 join CI_CLIENTE_SGTO_CANAL on CI_CLIENTE.swCustomerId=CI_CLIENTE_SGTO_CANAL.swCustomerId join CI_DIRECCIONES on CI_DIRECCIONES.swObjectId=CI_CLIENTE.swCustomerId -- 依次处理所有左连接 left outer join CI_CANAL_ASOCIADO on CI_PRODUCTO.swChnlPartnerId=CI_CANAL_ASOCIADO.swChnlPartnerId left outer join CI_PRODUCTO PROD_PADRE on CI_PRODUCTO.swParentInstProdId=PROD_PADRE.swInstProdId left outer join CI_HISTORICO on CI_PRODUCTO.swInstProdId=CI_HISTORICO.swObjectID left outer join CI_CARACT_CLIENTE on CI_CLIENTE.swCustomerId=CI_CARACT_CLIENTE.swCustomerId left outer join CI_LOTES_FACTURACION on CI_CONTRATO.swAgreementId=CI_LOTES_FACTURACION.swAgreementId
如果修改后结果仍然不一致,可以逐个注释左连接语句,分别对比原查询和改写查询的返回结果,快速定位到出错的连接条件。
内容的提问来源于stack exchange,提问作者noelia sancho
相关产品推荐
相关产品推荐

