看似简单的SQL,实则就是简单

来源:大数据左右手

昨天加班遇到一个SQL问题,本想把别人的SQL改下成SparkSQL,在YARN上运行,然而数据一直对不上,然后故事就来了。

如果下面有错误的认知,麻烦评论留言告诉我。

原SQL

⚠️说明:a.id,b.id没有空的,数据1:1,b.name可能存在空的

select 
  count(1)
from table_a a 
left join table_b b 
 on a.id = b.id and b.is_delete = 0 and b.name is not null
where 
exists(
  select 1 from  table_b c 
  where a.id = c.id and c.is_delete = 0
)

改后的

想法是:既然exists过滤了,为什么不直接inner join呢,于是乎:

select 
 count(1)
from table_a a 
inner join table_b b 
 on a.id = b.id and b.is_delete = 0  

求助群友

问了下群友,区别是我一直以为left join 后 b.name is not null并没什么用,就没有带,我问群友,下面这两个SQL有什么区别:

select 
  *
from table_a a 
left join table_b b 
 on a.id = b.id and b.is_delete = 0 
where 
exists(
  select 1 from  table_b c 
  where a.id = c.id and c.is_delete = 0
)



select 
  *
from table_a a 
inner join table_b b 
 on a.id = b.id and b.is_delete = 0  

群友问AI的结果这样的回答,不太对

自悟

然后仔细去品味这两个SQL有什么不同

-- (1)
select 
  a.id,
  b.id,
  b.name
from table_a a 
left join table_b b 
 on a.id = b.id and b.is_delete = 0 and b.name is not null
where 
exists(
  select 1 from  table_b c 
  where a.id = c.id and c.is_delete = 0
)


-- (2)

select 
  a.id,
  b.id,
  b.name
from table_a a 
inner join table_b b 
 on a.id = b.id and b.is_delete = 0  

数据table_a

id
1
2
3

数据table_b

idnameid_delete
1aa0
2bb0
3NULL0

结论: 

(1)sql计算会剔除掉 table_a 不符合 a.id = c.id and c.is_delete = 0 条件的数据。加上 name is not null。最后的数据会出现这两类情况:

a.id,null,null   # name为null,b表全部为空
a.id,b.id,b.name # 全
a.idb.idb.name
11aa
22bb
3NULLNULL

(2)sql计算后则会出现这两类情况:

a.id,b.id,null   
a.id,b.id,b.name # 全部有值
a.idb.idb.name
11aa
22bb
33NULL

所以,count的时候是没有问题的,两个都可以,如果是取具体的值有所区别。

拓展

如果a.id b.id 是1:n 呢?

数据table_a

id
1
2
3
10

数据table_b

idnameid_delete
1aa0
1NULL0
2bb0
3NULL0
-- (1)
select 
  a.id,
  b.id,
  b.name
from table_a a 
left join table_b b 
 on a.id = b.id and b.is_delete = 0 and b.name is not null
where 
exists(
  select 1 from  table_b c 
  where a.id = c.id and c.is_delete = 0
)
a.idb.idb.name
11aa
22bb
3NULLNULL
-- (2)

select 
   a.id,
  b.id,
  b.name
from table_a a 
inner join table_b b 
 on a.id = b.id and b.is_delete = 0 
a.idb.idb.name
11aa
11NULL
22bb
33NULL

所以,如果count的时候,1对n 相对于1:1 是有区别的。

最后

(1)菜就要学,就要钻研。 

(2)加班使人头疼,头脑不灵光。 

(3)具体问题,具体分析。


请使用浏览器的分享功能分享到微信等