张工是一名程序员,主要是做java开发,有次到一家软件公司面试软件开发岗位,面试官问了他两个问题,其中有一个问题是这样的这样:

说说left join和left semi join 有什么区别?

对于left join 张工在平时编写sql用得比较多,但对于left semi join张工很少用到,所以说不出个所以然来了。

面试官见张工回答不上来,由于张工应聘的岗位对编写sql的水平要求较高,面试官就没有继续再问下去了,叫他先回去等通知。

太扎心了!一个问题没回答上来就被叫回去等通知了。

我们来看看hive 中的left join和left semi join有什么区别。

对于left join 我们平时经常用到,就不再具体阐述了,重点来关注下left semi join。

left semi join

可以这么理解,LEFT SEMI JOIN (左半连接)是 IN/EXISTS 子查询的一种更高效的实现。

示例

select a.key,a.value
from table_name_a a
where a.key in (select b.key from table_name_b b)

我们可以把这条sql可改写成

select a.key,a.value
from table_name_a  a
left semi join table_name_b on(a.key=b.key)
  • left semi join特点

  1. left semi join 的限制, join子句中右边的表只能在 on子句中设置过滤条件,在 where子句、select子句或其他地方过滤都是不可取的。

  2. 因为left semi join 是只传递表的 join key 给 map 阶段,所以left semi join 中最后 select 的结果只许出现左表。

  3. 因为 left semi join 是 in(keySet) 的关系,遇到右表重复记录,左表会跳过,而 join 则会一直遍历。这就导致右表有重复值的情况下 left semi join 只产生一条,join 会产生很多条记录,也会导致影响 left semi join 的性能更高。

上面的描述可能不太好理解,理解起来还是很吃力,我们来举个实例。

先建立两张表(学生表和分数表)并将这两张表进行初始化数据。

  • --学生表

create table test.tb_student (id int comment 'id',name string comment '姓名',age int comment '年龄'
)

-- 初始化数据

INSERT INTO test.tb_student VALUES ('1', '张三', '7');
INSERT INTO test.tb_student VALUES ('2', '李四', '7');
INSERT INTO test.tb_student VALUES ('3', '王五', '7');
INSERT INTO test.tb_student VALUES ('4', '小爱', '7');

查询下test.tb_student表的数据

select * from test.tb_student

  • --分数表

create table test.course (id int comment '学生id',
name string comment '课程名称',
score string comment '分数'
)

-- 初始化数据

INSERT INTO test.course VALUES ('1', '语文','90');
INSERT INTO test.course VALUES ('1', '数学','100');
INSERT INTO test.course VALUES ('1', '英语','90');INSERT INTO test.course VALUES ('2', '语文','90');
INSERT INTO test.course VALUES ('2', '数学','90');
INSERT INTO test.course VALUES ('2', '英语','100');INSERT INTO test.course VALUES ('3', '语文','100');
INSERT INTO test.course VALUES ('3', '数学','100');
INSERT INTO test.course VALUES ('3', '英语','99');INSERT INTO test.course VALUES ('4', '语文','100');
INSERT INTO test.course VALUES ('4', '数学','100');
INSERT INTO test.course VALUES ('4', '英语','100');

查询下test.course表的数据

select * from test.course

通过上面的操作,我们已经成功创建了两张表并对其进行数据初始化。

下面我们来看看用left semi join和left join 操作后,查询出来的数据是怎样的?

-- left semi join

select * from test.tb_student a
left semi join test.course b on(a.id=b.id)

查询结果:

细心的你会发现,这不就是我们前面查询的test.tb_student表的数据吗?没错,确实是的,这是因为left semi join的select的结果中只允许出现t1(左表)表的字段

刚才的sql其实可以等价于

select * from test.tb_student a where a.id in (select id from test.course)

select * from test.tb_student a where exists (select 1 from test.course b where a.id=b.id)

他们执行的结果是一致的。

我们再来看看用left join查询出来会是什么样的结果。

--left join

select * from test.tb_student a
left join test.course b on a.id=b.id

查询结果:

从上面两者的执行结果我们可以清楚地看到left semi join 和 left join两者的区别了,这也应证了上面提到的关于left semi join的特点。

  1. left semi join 是只传递表的 join key 给 map 阶段,因此left semi join 中最后 select 的结果只许出现左表。

  2. left semi join 遇到右表重复记录,左表会跳过

面试时,要是面试官要是问起left join和left semi join 两者有什么区别这么细节的问题,比较友好地回答不妨参考这样的:

  1. left semi join join子句中右边的表只能在 on子句中设置过滤条件

  2. left semi join 中最后 select 的结果只许出现左表。

  3. 因为 left semi join 是 in(keySet) 的关系,遇到右表重复记录,左表会跳过,而 join 则会一直遍历。

要是能够回答出left semi join的特点,说明你完全有这方面的开发经验,相信能为这次面试加分。

总结:

  1. 对右表中重复key的处理方式差异:因为 left semi join 是 in(keySet) 的关系,遇到右表重复记录,左表会跳过,而 join on 则会一直遍历。

  2. left semi join 中最后 select 的结果只许出现左表,因为右表只有 join key 参与关联计算了,而 join on 默认是整个关系模型都参与计算了。

由于笔者知识及水平有限,文中错漏之处在所难免,如有不足之处,欢迎交流。

-END-

微信公众号:洪生鹏

面试官:说说left join和left semi join 两者有什么区别?相关推荐

  1. 转载:left join和left semi join的联系和区别

    1.联系 他们都是 hive join 方式的一种,join on 属于 common join(shuffle join/reduce join),而 left semi join 则属于 map ...

  2. left join和left semi join的联系和区别

    ** 转载:left join和left semi join的联系和区别 ** 1.联系 他们都是 hive join 方式的一种,join on 属于 common join(shuffle joi ...

  3. ​left join 和 left semi join区别 ​

    左连接与+号, 就是左边的表数据都要. select * from a,b where a.id=b.id(+); (+)写在where后面,不能与or/in连用,ui select * from a ...

  4. join left semi_HIVE--left semi join

    实验: hive> select * from b1; OK 1       003     20170511 1       004     20170512 1       005     ...

  5. join left semi_Hive的left join、left outer join和left semi join三者的区别

    Hive的Join的文档说明地址: https://cwiki.apache.org/confluence/display/Hive/LanguageManual%2BJoins 以下为两个测试数据表 ...

  6. left join和left semi join的区别

    --建表 create TABLE left_semi_join1(id int,name STRING );create TABLE left_semi_join2(id int,age STRIN ...

  7. Hive中的map join、left semi join和sort merge bucket join

    map join map join是将join双方比较小的表直接分发到各个 map进程的内存中,在map进程中进行join操作,这样就不用进行reduce步骤,从而提高了速度. 如果不指定mapjoi ...

  8. 面试官问:代理模式和装饰者模式有啥区别

    今天面试聊到了模式. 面试官问:装饰者模式了解吗,讲一下? 我:blabla... 面试官:那代理模式呢? 我:blabla.....(说完感觉怎么都一样呢) 果然,面试官又问了:那两者有什么区别呢? ...

  9. synchronized不能锁静态变量_面试官:请说一下对象锁和类锁的区别

    有锁才有自由 生活中不存在绝对的自由,绝对的自由通常对应的无序和混沌,只有在道德.法律.伦理的约束下的相对自由,才能使人感受到自由. 而在多线程编程中,锁是至关重要的,锁就是道德,就是法律约束,没有锁 ...

最新文章

  1. TensorFlow XLA优化与Memory
  2. mysql 存储引擎 面试_搞定PHP面试 - MySQL基础知识点整理 - 存储引擎
  3. 手写一个jsonp实现
  4. Python: Json串反序列化为自定义类对象
  5. 精选案例 | “虫虫音乐”如何做到搜索CTR提高150%
  6. GridView隐藏列, 并能读取列值的解决方法(转载)
  7. POE供电交换机应用方案及功能特性介绍
  8. 汇编语言:实验10 根据材料编程—1.显示字符串
  9. HDOJ 2066 HDU 2066 一个人的旅行 ACM 2066 IN HDU
  10. 编辑器图片上传 linux,summernote 富文本编辑器上传本地图片
  11. 练习:C#---for循环(整数和、阶乘、楼梯)
  12. ajax 用户验证js,js ajax验证用户名
  13. CIF进口货物流程图_FOB、CIF和CFR,你真的了解吗?
  14. php_js,举例说明JS调用PHP和PHP调用JS的方法_WEB前端开发
  15. Android.mk的一些FAQ
  16. Kotlin基础学习第3章—内置类型
  17. 基于Radon滤波反投影算法的CT图像重建matlab仿真
  18. alios是安卓吗_揭秘:阿里云OS和Android的主要区别是什么
  19. 微软和Google的盈利模式对比分析
  20. VirtulBox安装虚拟机(鼠标点击时)0x00000000指令引用的0x00000000内存该内存不能为written错误解决方案...

热门文章

  1. VS2017 函数模板和类模板的声明、定义和使用
  2. centos7搭建http代理ip TinyProxy 及验证是否有效(python)
  3. 复旦大学的计算机专业分数线,2018复旦大学分数线 各专业分数线是多少
  4. 如何把云服务器恢复到最原始的状态
  5. 单面机51小车程序_4千元牛排机实测!小白也能做出星级牛排,在家吃出法式餐厅感觉...
  6. Python爬虫实战—vmgrils图片网站
  7. 解决C# WPF的xaml突然报错XDG000 标签全不识别
  8. android signal 6,android signal 处理总结
  9. 人工智能“六步走”学习路线
  10. Matlab三相全桥逆变电路的仿真