You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MSSQL 2008R2中UNION存在与否导致同查询返回不同值问题咨询

问题根因

核心原因是对UNION的去重逻辑认知有误,加上第一个CTE子句选的列太少,导致大量有效数据被错误去重,最终汇总值偏小:

  • UNION的实际执行逻辑是:将两个子查询的结果集拼接后,对全量数据做去重——只要两行数据的SELECT列表所有列值完全相同,不管这两行是来自同一个子查询还是两个不同子查询,都会被判定为重复,仅保留1行。这和UNION ALL直接保留所有行、不做去重的逻辑有本质区别。
  • 第一个查询里查CED数据的分支,只选了src和Costo两个列:其中src是固定常量'CED',相当于所有行的第一列值完全一样,去重判定就只看Costo的值是否相等。
    而DM_VRECostPerCid_CED视图本身是按CodAzi、CID、CdC、CoGe等多个业务维度分组算出来的结果,不同维度分组下的成本值Costo重复是非常常见的情况(比如多个部门的小额办公成本金额相同、大量0值调整项等)。这些业务上完全独立的有效数据,就因为只选了两个列,被UNION判定为重复行大量删除,最终sum出来的结果比真实值小近40%完全符合这个现象。
  • 第二个查询结果正确也很好解释:
    • 这个查询里UNION关联ADJ表的代码全被注释了,本质就是单查视图,根本不会触发UNION的去重逻辑;
    • 同时这个查询的SELECT列表带了CodAzi、CID、CdC、CoGe等所有分组维度列,这些列的组合在视图输出里是全局唯一的,就算Costo值一样,整行内容也不会重复,自然不会丢数据。
验证方法

把第一个查询里的UNION改成UNION ALL再执行,CED对应的汇总值会和第二个查询的结果完全一致:

declare @datCed DATE = '2022-01-31'
;with t as (        
    SELECT 'CED' AS src, Costo      
    FROM DM_VRECostPerCid_CED   
    WHERE DatCed = @datCed
UNION ALL
    SELECT 'ADJ' AS src, Importo
    FROM dbo.DM_PY_Adjusted     
    WHERE DatCed = @datCed
)       
select src, sum(costo)  
from t
group by src        

注意:执行计划里看到的"Concatenation(串联)"只是结果集拼接的步骤,不管是UNION还是UNION ALL都会有这个操作。UNION在串联之后还会额外执行排序去重(Distinct Sort)的步骤,不要把串联当成UNION的全部执行逻辑。

注意事项
  • 除非明确需要对合并后的结果去重,否则多结果集拼接一律优先用UNION ALL,不仅性能更好(省去了排序去重的开销),也不会出现这种误删有效数据的问题;
  • 如果确实要使用UNION,一定要保证SELECT列表里包含足够的唯一标识字段(比如业务主键、维度组合字段),避免不同业务数据因为查询列值重复被误去重。

内容的提问来源于stack exchange,提问作者Paolo Ursini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 18:48:25