使用left join时导致数据丢失情况示例

建基础表


--表1: 姓名 
create table app.test_boa_1 (id string ,name string );
insert into app.test_boa_1 values (1,'安妮');
insert into app.test_boa_1 values (2,'盖伦');
insert into app.test_boa_1 values (3,'光辉');

--表2:工资 
create table app.test_boa_2 (id string ,sal string );
insert into app.test_boa_2 values (1,'3600');
insert into app.test_boa_2 values (3,'500');

--表3:部门
create table app.test_boa_3 (id string ,dep string );
insert into app.test_boa_3 values (1,'德玛西亚');
insert into app.test_boa_3 values (2,'德玛西亚');
insert into app.test_boa_3 values (3,'德玛西亚');
  • 在德玛西亚,盖伦属于义务工,没有工资>>_<<

导致数据丢失的left join

注意:下面代码是从表2中取得id字段

select  
 t2.id
,t1.name
,t2.sal
,t3.dep 
from app.test_boa_1 t1      --表1: 姓名
left join app.test_boa_2 t2 --表2:工资
on t1.id=t2.id 
left join app.test_boa_3 t3 --表3:部门
on t1.id=t3.id 
; 
  • 上面代码的查询结果集如下,但会导致id=2的数据无法在结果表查到,导致数据在逻辑上丢失。
id 姓名 工资 部门
1 安妮 3600 德玛西亚
3 光辉 500 德玛西亚
null 盖伦 null 德玛西亚
  • 由于盖伦没有工资,所以再表1和表2关联的时候取表2的ID字段是取不到的,结果集中盖伦对应的ID为null 。这样就导致无论如何也查不到盖伦这个英雄的信息。 (数据丢失)虽然在物理上依旧有盖伦的这条记录,但是无法被select到,从逻辑上丢失了这个数据。
  • 注意:如果sql执行计划是 表1和表2关联结果集去关联表3,那么最终结果集中盖伦的部门也会是null。
  • 上述sql的结果集可能在不同数据库中有不同的结果

正确的写法

将id字段换成表1(主表)取值,可避免这种情况

--修改为如下代码就可以了(标签数据尽量从主表出,不然容易导致逻辑丢失)
select  
 t1.id
,t1.name
,t2.sal
,t3.dep 
from app.test_boa_1 t1
left join app.test_boa_2 t2 
on t1.id=t2.id 
left join app.test_boa_3 t3 
on t1.id=t3.id 
; 
  • 上述代码的查询结果为:
id 姓名 工资 部门
1 安妮 3600 德玛西亚
3 光辉 500 德玛西亚
2 盖伦 null 德玛西亚

总结

1、用于关联的字段尽量从主表出数
2、sql开发时注意表中的数据质量和完整度,关注那些数据不全出现的null对后续数据集处理的影响。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐