使用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对后续数据集处理的影响。