如何在SQL SELECT中无需额外查询比较子查询返回的列?
问题描述
我正在编写一条相对复杂的SQL语句,该语句从多张表中查询数据,包含不少子查询与连接操作。我希望在最终的数据集中,既返回原始数据,也返回原始数据间的比较结果。当原始数据通过Join获取时我可以实现这一点,但如果原始数据来自子查询,是否也能做到?
例如,我有如下查询:
SELECT A ,(SELECT B FROM BETA WHERE Row = ALPHA.Betalink) B FROM ALPHA WHERE A > 1
能否在不添加额外Select语句的情况下,新增一列来比较A和B?目前我所知的唯一解决方法是将上述查询作为子查询,在外层再进行查询:
SELECT A ,B ,greater(A,B) FROM (SELECT A ,(SELECT B FROM BETA WHERE Row = ALPHA.Betalink) B FROM ALPHA WHERE A > 1 )
提前致谢(TIA)
解决方案
可以做到,不需要嵌套额外的外层查询,下面提供两种可行的方法:
方法1:重复子查询(简单直接但存在性能损耗)
直接在比较函数中重复调用子查询,就能在同一层SELECT中生成比较列:
SELECT A, (SELECT B FROM BETA WHERE Row = ALPHA.Betalink) B, GREATER(A, (SELECT B FROM BETA WHERE Row = ALPHA.Betalink)) AS A_vs_B FROM ALPHA WHERE A > 1
注意:这种方式会让子查询执行两次,数据量较大时可能存在性能问题。
方法2:使用横向连接(性能更优,推荐)
如果你的数据库支持LATERAL JOIN(如PostgreSQL、MySQL 8.0+)或CROSS/OUTER APPLY(如SQL Server),可以把子查询转换为横向连接,这样子查询结果能在同一层SELECT中直接引用,且只会执行一次:
PostgreSQL/MySQL 8.0+ 写法
SELECT ALPHA.A, BETA_SUB.B, GREATER(ALPHA.A, BETA_SUB.B) AS A_vs_B FROM ALPHA LEFT JOIN LATERAL ( SELECT B FROM BETA WHERE Row = ALPHA.Betalink ) BETA_SUB ON TRUE WHERE ALPHA.A > 1
SQL Server 写法
SELECT ALPHA.A, BETA_SUB.B, GREATER(ALPHA.A, BETA_SUB.B) AS A_vs_B FROM ALPHA OUTER APPLY ( SELECT B FROM BETA WHERE Row = ALPHA.Betalink ) BETA_SUB WHERE ALPHA.A > 1
这种方式既满足“不添加额外Select语句”的要求,又避免了重复执行子查询的性能问题,是更优的解决方案。
内容的提问来源于stack exchange,提问作者Cameron
相关产品推荐
相关产品推荐

