Oracle中无公共列的两个sum聚合结果如何正确拼接为单行
错误原因
两种写法的问题非常明确:
UNION ALL的逻辑是纵向拼接结果集,两个独立查询的结果会按行堆叠,自然会输出两行,无法在同一行展示两个不同指标。- 直接对两张原表做
CROSS JOIN会生成笛卡尔积:假设dba_data_files有m条记录、dba_segments有n条记录,关联后会生成m*n条记录,此时再做sum()聚合,每条记录的bytes值会被重复累加n/m次,算出来的结果会比真实值大几十上百倍,完全失真。
正确实现方案
两个聚合逻辑本身完全独立、各自只返回1个单值,只需要先分别完成两个表的聚合计算,再对两个单值结果做列拼接即可,此时不会出现笛卡尔积重复计算的问题:
SELECT t.total_size AS "Total Size", u.used_space AS "Used space" FROM (SELECT SUM(bytes/1024/1024/1024) total_size FROM dba_data_files) t, (SELECT SUM(bytes/1024/1024/1024) used_space FROM dba_segments) u;
上面的写法用了Oracle通用的隐式交叉连接,兼容所有Oracle版本。如果使用12c及以上版本,也可以用CTE写法提升可读性:
WITH total_calc AS (SELECT SUM(bytes/1024/1024/1024) AS "Total Size" FROM dba_data_files), used_calc AS (SELECT SUM(bytes/1024/1024/1024) AS "Used space" FROM dba_segments) SELECT * FROM total_calc CROSS JOIN used_calc;
结果验证
执行后就能得到预期的正确输出:
Total Size Used space ---------- ----------- 90.9035645 74.4375
核心原则:对没有关联关系的多张表做独立聚合统计时,永远先在子查询/CTE里完成单表的聚合,拿到单值结果后再做列合并,绝对不要直接关联原始表再聚合,否则必然出现笛卡尔积导致的数值计算错误。
内容的提问来源于stack exchange,提问作者mrgvr
相关产品推荐
相关产品推荐

