Oracle中能否引用SELECT列别名?子查询别名无法参与计算如何解决
SQL查询引用同层SELECT列别名的解决方法
你遇到的问题是SQL标准的逻辑执行顺序限制导致的:数据库执行查询时,会按顺序先处理FROM/JOIN、WHERE、GROUP BY、HAVING子句,最后才处理SELECT子句的列计算和别名分配,因此同层级SELECT里定义的keszlet别名,无法在同层级的其他列计算中直接引用。
以下是三种常用的解决方案:
方案1:使用LATERAL横向连接(推荐,性能最优)
LATERAL JOIN允许你在FROM子句中定义可被后续计算引用的标量计算,只会执行一次子查询,效率最高,Oracle 12c+、MySQL 8.0+、PostgreSQL等主流数据库均支持:
SELECT ARUTORZS.ARUKOD, ARUTORZS.ARUNEV, k.keszlet, ARUTELEP.RKOD, ARUTELEP.ZONA_KOMISSIOS, ARUTORZS.GYARTO_KOD, UGYFEL.ORACLE_KOD, UGYFEL.SZAML_NEV, ARUTORZS.SULY, ARUTORZS.SULY * k.keszlet / 1000 AS SULYKG, ARUTORZS.REL_LEJ, ARUTORZS.GYUJTO, ARUTORZS.RAKLAP_MENNY FROM STOREIS.ARUTORZS LEFT OUTER JOIN STOREIS.ARUTELEP ON ARUTELEP.TH_KOD='P' AND ARUTELEP.ARUKOD=ARUTORZS.ARUKOD LEFT OUTER JOIN STOREIS.UGYFEL ON UGYFEL.UGYF_KOD=ARUTORZS.GYARTO_KOD -- 横向连接预计算keszlet,后续可直接引用 LEFT JOIN LATERAL ( SELECT SUM(MENNYISEG) AS keszlet FROM STOREIS.KESZLET LEFT OUTER JOIN STOREIS.THELY ON THELY.TH=KESZLET.TH LEFT OUTER JOIN STOREIS.ZONA ON ZONA.ZONAKOD=THELY.ZONA LEFT OUTER JOIN STOREIS.ARUTELEP ate ON ate.TH_KOD='P' AND ate.ARUKOD=KESZLET.ARUKOD LEFT OUTER JOIN STOREIS.RAKTAR ON RAKTAR.RAKTAR=KESZLET.RKOD WHERE KESZLET.ARUKOD=ARUTORZS.ARUKOD ) k ON 1=1 WHERE ARUTELEP.RKOD>=100 AND ARUTELEP.RKOD<=199
方案2:使用CTE(公共表表达式)包裹查询
可读性高,适合逻辑复杂的多步计算场景:
WITH base_query AS ( SELECT ARUTORZS.ARUKOD, ARUTORZS.ARUNEV, (SELECT SUM(MENNYISEG) FROM STOREIS.KESZLET LEFT OUTER JOIN STOREIS.THELY ON THELY.TH=KESZLET.TH LEFT OUTER JOIN STOREIS.ZONA ON ZONA.ZONAKOD=THELY.ZONA LEFT OUTER JOIN STOREIS.ARUTELEP ate ON ate.TH_KOD='P' AND ate.ARUKOD=KESZLET.ARUKOD LEFT OUTER JOIN STOREIS.RAKTAR ON RAKTAR.RAKTAR=KESZLET.RKOD WHERE KESZLET.ARUKOD=ARUTORZS.ARUKOD ) AS keszlet, ARUTELEP.RKOD, ARUTELEP.ZONA_KOMISSIOS, ARUTORZS.GYARTO_KOD, UGYFEL.ORACLE_KOD, UGYFEL.SZAML_NEV, ARUTORZS.SULY, ARUTORZS.REL_LEJ, ARUTORZS.GYUJTO, ARUTORZS.RAKLAP_MENNY FROM STOREIS.ARUTORZS LEFT OUTER JOIN STOREIS.ARUTELEP ON ARUTELEP.TH_KOD='P' AND ARUTELEP.ARUKOD=ARUTORZS.ARUKOD LEFT OUTER JOIN STOREIS.UGYFEL ON UGYFEL.UGYF_KOD=ARUTORZS.GYARTO_KOD WHERE ARUTELEP.RKOD>=100 AND ARUTELEP.RKOD<=199 ) SELECT *, SULY * keszlet / 1000 AS SULYKG FROM base_query
方案3:重复子查询(兼容所有数据库版本)
如果数据库版本不支持上述两种语法,可以直接把keszlet的子查询复制到需要引用的位置,大多数数据库的优化器会自动识别重复子查询,不会重复执行,无额外性能损耗:
SELECT ARUTORZS.ARUKOD, ARUTORZS.ARUNEV, (SELECT SUM(MENNYISEG) FROM ((((STOREIS.KESZLET LEFT OUTER JOIN STOREIS.THELY ON THELY.TH=KESZLET.TH) LEFT OUTER JOIN STOREIS.ZONA ON ZONA.ZONAKOD=THELY.ZONA) LEFT OUTER JOIN STOREIS.ARUTELEP ON ARUTELEP.TH_KOD='P' AND ARUTELEP.ARUKOD=KESZLET.ARUKOD) LEFT OUTER JOIN STOREIS.RAKTAR ON RAKTAR.RAKTAR=KESZLET.RKOD) WHERE KESZLET.ARUKOD=ARUTORZS.ARUKOD ) AS keszlet, ARUTELEP.RKOD, ARUTELEP.ZONA_KOMISSIOS, ARUTORZS.GYARTO_KOD, UGYFEL.ORACLE_KOD, UGYFEL.SZAML_NEV, ARUTORZS.SULY, -- 直接重复keszlet子查询完成计算 ARUTORZS.SULY*(SELECT SUM(MENNYISEG) FROM ((((STOREIS.KESZLET LEFT OUTER JOIN STOREIS.THELY ON THELY.TH=KESZLET.TH) LEFT OUTER JOIN STOREIS.ZONA ON ZONA.ZONAKOD=THELY.ZONA) LEFT OUTER JOIN STOREIS.ARUTELEP ON ARUTELEP.TH_KOD='P' AND ARUTELEP.ARUKOD=KESZLET.ARUKOD) LEFT OUTER JOIN STOREIS.RAKTAR ON RAKTAR.RAKTAR=KESZLET.RKOD) WHERE KESZLET.ARUKOD=ARUTORZS.ARUKOD )/1000 AS SULYKG, ARUTORZS.REL_LEJ, ARUTORZS.GYUJTO, ARUTORZS.RAKLAP_MENNY FROM ((STOREIS.ARUTORZS LEFT OUTER JOIN STOREIS.ARUTELEP ON ARUTELEP.TH_KOD='P' AND ARUTELEP.ARUKOD=ARUTORZS.ARUKOD) LEFT OUTER JOIN STOREIS.UGYFEL ON UGYFEL.UGYF_KOD=ARUTORZS.GYARTO_KOD) WHERE ARUTELEP.RKOD>=100 AND ARUTELEP.RKOD<=199
内容的提问来源于stack exchange,提问作者Maestro
相关产品推荐
相关产品推荐

