踩坑,union后数据少了

本文探讨了使用 SQL 中的 UNION 在处理重复数据时可能遇到的问题,特别是在分组数据后再使用 UNION 合并结果集的情况。作者通过具体案例展示了 UNION 的工作原理,并提出了 UNION ALL 作为备选方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

union后数据少了,不能包含重复行

之前一直关注union在两个表的连接后出现的不包含重复行,我这次是在分组数据后进行两个结果集的union。分组后的数据如下,出现了两个时间完全相同的数据,导致了我再用union连接的时候只出现了一条数据。

我在用的时候一直有个问题困扰了我,因为我的union的结果集一个空的,导致了我一直误以为是空数据集的问题。如下面的展示的sql代码,查询的结果为18条。

select *
  from (select dtlrf.jyje,
               dtlrf.yhid,
               nvl(to_number(dtlrf.zjlx), 0) zjlx,
               dtlrf.czybh,
               dtlrf.czyxm,
               dtlrf.jysj
          from ipay.order_detl dtlrf
         where 1 = 1
           and dtlrf.paystate = 'repaid'
           and (dtlrf.cqtfbs not in ('1', '2') or dtlrf.cqtfbs is null)
           and dtlrf.czybh = '493'
           and dtlrf.jyje = 500
           and dtlrf.jysj >= '20210406000000'
           and dtlrf.jysj <= '20210406235918'
        union
        -- 下面的sql 查询结果为空
        select cash.jyje,
               'XJZF' yhid,
               0 zjlx,
               cash.czybh,
               cash.czyxm,
               cash.jysj
          from ipay.overtocash_refund cash
         where 1 = 1
           and cash.state = 'repaid'
           and cash.czybh = '493') a
 order by a.jysj

查询的的结果集:
在这里插入图片描述

第二个这种情况下的查询结果为19条,没有用union。相同的数据会展示出来。

select dtlrf.jyje,
       dtlrf.yhid,
       nvl(to_number(dtlrf.zjlx), 0) zjlx,
       dtlrf.czybh,
       dtlrf.czyxm,
       dtlrf.jysj
  from ipay.order_detl dtlrf
 where 1 = 1
   and dtlrf.paystate = 'repaid'
   and (dtlrf.cqtfbs not in ('1', '2') or dtlrf.cqtfbs is null)
   and dtlrf.czybh = '493'
   and dtlrf.jyje = 500
   and dtlrf.jysj >= '20210406000000'
   and dtlrf.jysj <= '20210406235918'
 order by dtlrf.jysj

查询结果为:
在这里插入图片描述

总结:
union的优势会对数据集进行:
1.排序
2.去重
但是如果有完全相同的数据情况下就会漏掉,我之前觉得不会有两笔交易的时间会完全相同,但是看来完全有可能存在的。所以分组之后的数据字段一般比较少,重复的概率也会增大,在没有排序的情况下,union一定要慎用。union all也是不错的选择。

### SQL `UNION ALL` 后数据丢失的原因分析 当遇到SQL查询中使用`UNION ALL`操作符之后发生的数据丢失现象,通常并非由`UNION ALL`本身引起。实际上,`UNION ALL`会保留两个结果集中的所有记录,包括重复项。因此,在正常情况下不会导致任何数据行被丢弃。 然而,可能出现看似“数据丢失”的情形往往源于以下几个方面: #### 查询逻辑错误 如果在构建涉及多个子查询的复杂语句时未能正确处理条件或连接方式,则可能导致某些预期之外的结果过滤掉部分本应存在的记录[^1]。 ```sql -- 错误示范:假设这里存在逻辑上的失误使得一些应该返回的行未被选中 SELECT * FROM tableA WHERE conditionX UNION ALL SELECT * FROM tableB WHERE NOT EXISTS (conditionY); ``` #### 表结构差异 参与联合运算的不同表之间列的数量不匹配或是数据类型的兼容性问题也可能引发异常行为。即使表面上看不出来明显的报错提示,但在实际执行过程中却影响到了最终输出的内容完整性[^2]。 ```sql -- 假设tableC有一列额外的timestamp而其他表没有此属性 SELECT id,name,value FROM tableD UNION ALL SELECT id,name,value,created_at AS timestamp -- 这里可能会因为列数不同而导致问题 FROM tableC; ``` #### 排序与分页的影响 有时为了优化性能会对整个结果集应用ORDER BY加上LIMIT之类的限制条款;如果不小心设置了不当参数的话,确实会造成特定范围内的条目无法显示出来,给人一种数据遗失的感觉[^3]。 ```sql WITH combined_data AS ( SELECT col1,col2,... FROM sourceTable1 UNION ALL SELECT col1,col2,... FROM sourceTable2 ) SELECT * FROM combined_data ORDER BY some_column DESC LIMIT 10; -- 如果总数不足10条则后面的部分自然就看不见了 ``` ### 解决方案建议 针对上述提到的各种潜在因素,可采取如下措施加以预防和修正: - **仔细审查SQL语法**:确保各个组成部分之间的关系表达清晰无歧义,并且对于涉及到JOIN的地方特别留意其作用机制以及所附加的约束条件是否合理。 - **统一各表定义**:提前确认好待组合对象间的关键字段数目一致性和类型一致性,必要时可通过CAST()函数转换目标域格式以达成一致化标准。 - **谨慎设置排序/分页选项**:除非绝对需要,否则尽量避免直接给最外层包裹一层带有TOP N或者FETCH FIRST n ROWS ONLY这样的限定字句,转而在获取全量后再做进一步筛选更为稳妥可靠。 最后值得注意的是,虽然题目提及了Hive环境下LEFT JOIN带来的挑战,但这并不意味着相同模式下的`UNION ALL`也会遭遇同样的困扰。两者属于不同类型的操作符,适用场景也有所区别,故应当分别对待各自面临的具体难题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值