left semi join 与join 的区别

本文深入探讨了SQL中的左半开连接(LEFTSEMIJOIN)概念,解释了它如何返回左边表满足特定条件的记录,对比了其与常见内连接(INNER JOIN)的区别。通过具体示例展示了LEFTSEMIJOIN在处理数据时的特性和限制,特别是在面对右表重复key时的不同处理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LEFT SEMI JOIN:左半开连接会返回左边表的记录,前提是其记录对于右边表满足ON语句中的判定条件。对于常见的内连接(INNER JOIN),这是一个特殊的,优化了的情况。大多数的SQL方言会通过in.......exists结构来处理这种情况。

准备表:

create table dcx1107(
id bigint
);
insert into dcx1107 values(-1);
insert into dcx1107 values(1);

create table dcx_2(
id bigint
,role string
);

insert into dcx_2 values(-1,'C1');
insert into dcx_2 values(1,'C1');
insert into dcx_2 values(1,'C2');

查询数据:

--join的select的结果中可以有t1(左表),t2(右表)两张表的字段
select 
t1.id,t2.role
from dcx1107 t1
join dcx_2 t2
on t1.id=t2.id;

结果:

--left semi join的select的结果中只允许出现t1(左表)表的字段
select 
t1.id
from dcx1107 t1
left semi join dcx_2 t2
on (t1.id=t2.id);

--等价于
 select 
t1.id
from dcx1107 t1
where id in (select id from dcx_2)
;

--等价于
 select 
t1.id
from dcx1107 t1
where EXISTS (select 1 from dcx_2 t2 where t1.id=t2.id)

结果:

这样写会报错
select 
t1.id,t2.role
from dcx1107 t1
left semi join dcx_2 t2
on (t1.id=t2.id);

总结:

对待右表中重复key的处理方式差异:因为 left semi join 是 in(keySet) 的关系,遇到右表重复记录,左表会跳过,而 join on 则会一直遍历。
left semi join 中最后 select 的结果只许出现左表,因为右表只有 join key 参与关联计算了,而 join on 默认是整个关系模型都参与计算了。

### Left Semi Join 的作用 `LEFT SEMI JOIN` 是一种特殊的 `JOIN` 操作,主要用于实现类似于 `IN` 或 `EXISTS` 子查询的功能,但其在执行效率语义上具有独特优势。其核心作用是从左表中筛选出那些在右表中存在匹配记录的行,但不会返回右表中的任何列。这种操作特别适用于需要验证左表中的记录是否存在于右表中的场景,例如数据过滤数据匹配[^2]。 `INNER JOIN` 不同,`LEFT SEMI JOIN` 只会返回左表中的列,并且在右表中存在重复记录时,左表中的记录只会被返回一次,而不是多次。这种特性使得 `LEFT SEMI JOIN` 在性能上通常优于 `INNER JOIN`,尤其是在右表中存在大量重复记录的情况下[^1]。 ### Left Semi Join 的使用限制 - **右表的过滤条件只能在 ON 子句中设置**:`LEFT SEMI JOIN` 不支持在 `WHERE` 子句或 `SELECT` 子句中对右表进行过滤操作,所有的过滤条件必须放在 `ON` 子句中。 - **只传递左表的字段**:由于 `LEFT SEMI JOIN` 不会返回右表中的任何列,因此其结果集仅包含左表的字段。 - **不支持右表的聚合操作**:由于右表仅用于匹配条件,因此无法在 `LEFT SEMI JOIN` 中直接使用右表的聚合操作或字段[^3]。 ### Left Semi Join 的使用示例 假设存在两个表:`orders`(订单表) `customers`(客户表),其中 `orders` 表包含字段 `order_id` `customer_id`,而 `customers` 表包含字段 `customer_id` `customer_name`。如果需要查询所有在 `customers` 表中存在对应客户的订单记录,可以使用 `LEFT SEMI JOIN` 实现。 #### SQL 查询示例 ```sql SELECT orders.* FROM orders LEFT SEMI JOIN customers ON orders.customer_id = customers.customer_id; ``` 上述查询会返回 `orders` 表中所有 `customers` 表中 `customer_id` 匹配的记录。由于 `LEFT SEMI JOIN` 的特性,结果集中不会包含 `customers` 表中的任何字段,且即使 `customers` 表中存在多个相同 `customer_id` 的记录,`orders` 表中的记录也只会被返回一次[^2]。 ### Left Semi Join Inner Join区别 - **结果集的组成**:`LEFT SEMI JOIN` 仅返回左表中的字段,而 `INNER JOIN` 会返回两个表中匹配的字段。 - **重复记录的处理**:当右表中存在重复记录时,`LEFT SEMI JOIN` 会确保左表中的记录仅被返回一次,而 `INNER JOIN` 会返回所有匹配的记录,导致结果集中出现多条相同的左表记录。 - **性能差异**:由于 `LEFT SEMI JOIN` 仅关注左表中的记录是否存在于右表中,而不需要遍历右表的所有匹配记录,因此其性能通常优于 `INNER JOIN`,尤其是在右表数据量较大的情况下[^1]。 ### Left Semi Join IN/EXISTS 子查询的关系 在 Hive 0.13 及更高版本中,`LEFT SEMI JOIN` 被设计为一种高效的实现方式,用于替代传统的 `IN` 或 `EXISTS` 子查询。例如,以下 `EXISTS` 子查询可以等价地转换为 `LEFT SEMI JOIN` 查询: #### 使用 EXISTS 子查询的 SQL 查询 ```sql SELECT orders.* FROM orders WHERE EXISTS ( SELECT 1 FROM customers WHERE orders.customer_id = customers.customer_id ); ``` #### 等价的 LEFT SEMI JOIN 查询 ```sql SELECT orders.* FROM orders LEFT SEMI JOIN customers ON orders.customer_id = customers.customer_id; ``` 两者在语义上是等价的,但 `LEFT SEMI JOIN` 通常在执行效率上更具优势,因为其能够更高效地处理大规模数据集[^3]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值