面试官:说说left join和left semi join 两者有什么区别?
张工是一名程序员,主要是做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特点
left semi join 的限制, join子句中右边的表只能在 on子句中设置过滤条件,在 where子句、select子句或其他地方过滤都是不可取的。
因为left semi join 是只传递表的 join key 给 map 阶段,所以left semi join 中最后 select 的结果只许出现左表。
因为 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的特点。
left semi join 是只传递表的 join key 给 map 阶段,因此left semi join 中最后 select 的结果只许出现左表。
left semi join 遇到右表重复记录,左表会跳过
面试时,要是面试官要是问起left join和left semi join 两者有什么区别这么细节的问题,比较友好地回答不妨参考这样的:
left semi join join子句中右边的表只能在 on子句中设置过滤条件
left semi join 中最后 select 的结果只许出现左表。
因为 left semi join 是 in(keySet) 的关系,遇到右表重复记录,左表会跳过,而 join 则会一直遍历。
要是能够回答出left semi join的特点,说明你完全有这方面的开发经验,相信能为这次面试加分。
总结:
对右表中重复key的处理方式差异:因为 left semi join 是 in(keySet) 的关系,遇到右表重复记录,左表会跳过,而 join on 则会一直遍历。
left semi join 中最后 select 的结果只许出现左表,因为右表只有 join key 参与关联计算了,而 join on 默认是整个关系模型都参与计算了。
由于笔者知识及水平有限,文中错漏之处在所难免,如有不足之处,欢迎交流。
-END-
微信公众号:洪生鹏
面试官:说说left join和left semi join 两者有什么区别?相关推荐
- 转载:left join和left semi join的联系和区别
1.联系 他们都是 hive join 方式的一种,join on 属于 common join(shuffle join/reduce join),而 left semi join 则属于 map ...
- left join和left semi join的联系和区别
** 转载:left join和left semi join的联系和区别 ** 1.联系 他们都是 hive join 方式的一种,join on 属于 common join(shuffle joi ...
- left join 和 left semi join区别
左连接与+号, 就是左边的表数据都要. select * from a,b where a.id=b.id(+); (+)写在where后面,不能与or/in连用,ui select * from a ...
- join left semi_HIVE--left semi join
实验: hive> select * from b1; OK 1 003 20170511 1 004 20170512 1 005 ...
- join left semi_Hive的left join、left outer join和left semi join三者的区别
Hive的Join的文档说明地址: https://cwiki.apache.org/confluence/display/Hive/LanguageManual%2BJoins 以下为两个测试数据表 ...
- left join和left semi join的区别
--建表 create TABLE left_semi_join1(id int,name STRING );create TABLE left_semi_join2(id int,age STRIN ...
- Hive中的map join、left semi join和sort merge bucket join
map join map join是将join双方比较小的表直接分发到各个 map进程的内存中,在map进程中进行join操作,这样就不用进行reduce步骤,从而提高了速度. 如果不指定mapjoi ...
- 面试官问:代理模式和装饰者模式有啥区别
今天面试聊到了模式. 面试官问:装饰者模式了解吗,讲一下? 我:blabla... 面试官:那代理模式呢? 我:blabla.....(说完感觉怎么都一样呢) 果然,面试官又问了:那两者有什么区别呢? ...
- synchronized不能锁静态变量_面试官:请说一下对象锁和类锁的区别
有锁才有自由 生活中不存在绝对的自由,绝对的自由通常对应的无序和混沌,只有在道德.法律.伦理的约束下的相对自由,才能使人感受到自由. 而在多线程编程中,锁是至关重要的,锁就是道德,就是法律约束,没有锁 ...
最新文章
- TensorFlow XLA优化与Memory
- mysql 存储引擎 面试_搞定PHP面试 - MySQL基础知识点整理 - 存储引擎
- 手写一个jsonp实现
- Python: Json串反序列化为自定义类对象
- 精选案例 | “虫虫音乐”如何做到搜索CTR提高150%
- GridView隐藏列, 并能读取列值的解决方法(转载)
- POE供电交换机应用方案及功能特性介绍
- 汇编语言:实验10 根据材料编程—1.显示字符串
- HDOJ 2066 HDU 2066 一个人的旅行 ACM 2066 IN HDU
- 编辑器图片上传 linux,summernote 富文本编辑器上传本地图片
- 练习:C#---for循环(整数和、阶乘、楼梯)
- ajax 用户验证js,js ajax验证用户名
- CIF进口货物流程图_FOB、CIF和CFR,你真的了解吗?
- php_js,举例说明JS调用PHP和PHP调用JS的方法_WEB前端开发
- Android.mk的一些FAQ
- Kotlin基础学习第3章—内置类型
- 基于Radon滤波反投影算法的CT图像重建matlab仿真
- alios是安卓吗_揭秘:阿里云OS和Android的主要区别是什么
- 微软和Google的盈利模式对比分析
- VirtulBox安装虚拟机(鼠标点击时)0x00000000指令引用的0x00000000内存该内存不能为written错误解决方案...
热门文章
- VS2017 函数模板和类模板的声明、定义和使用
- centos7搭建http代理ip TinyProxy 及验证是否有效(python)
- 复旦大学的计算机专业分数线,2018复旦大学分数线 各专业分数线是多少
- 如何把云服务器恢复到最原始的状态
- 单面机51小车程序_4千元牛排机实测!小白也能做出星级牛排,在家吃出法式餐厅感觉...
- Python爬虫实战—vmgrils图片网站
- 解决C# WPF的xaml突然报错XDG000 标签全不识别
- android signal 6,android signal 处理总结
- 人工智能“六步走”学习路线
- Matlab三相全桥逆变电路的仿真