什么是数据库中的半联接?

Posted

技术标签:

【中文标题】什么是数据库中的半联接?【英文标题】:What is semi-join in database? 【发布时间】:2017-07-04 03:10:27 【问题描述】:

我在尝试理解半联接的概念以及它与传统联接有何不同时遇到了麻烦。我已经尝试了一些文章,但对解释不满意,有人可以帮我理解吗?

【问题讨论】:

检查关系中是否存在匹配条件的任何元组。 awads.net/wp/2007/05/01/… 【参考方案1】:

简单的例子。让我们使用左外连接选择成绩的学生:

SELECT DISTINCT s.id
FROM  students s
      LEFT JOIN grades g ON g.student_id = s.id
WHERE g.student_id IS NOT NULL

现在与左半连接相同:

SELECT s.id
FROM  students s
WHERE EXISTS (SELECT 1 FROM grades g
              WHERE g.student_id = s.id)

后者通常更有效(取决于具体的 DBMS 和查询优化器)。

【讨论】:

为什么在WHERE EXISTS 语句的第一部分总是说SELECT 1 @BrentB 必须选择某些东西,但不需要实际数据(一个体面的优化器应该能够优化掉任何替代方案,如SELECT *,所以它更多的是加强人类同行的意图没有使用数据) 为什么效率更高? @JamesWierzba 查询优化器可能会识别出它们是相同的,并使用相同的查询计划来运行任一查询。但是,从概念上讲,在第一个查询中,您将首先找到每个学生的所有成绩,然后删除所有没有成绩的学生,然后删除重复的学生,直到剩下唯一的学生。在第二个查询中,您逐个学生检查该学生是否至少有一个成绩。因此无需枚举所有成绩或在最后删除重复的学生 ID。同样,优化器可能足够聪明,可以对两者使用相同的算法 x left join y on c where y.a is not nullx inner join y on c。在第一个查询中,左连接是不必要的并且具有误导性。 “效率更高” 错误。依赖DBMS优化器/实现,优化简单。【参考方案2】:

据我所知,支持SEMIJOIN/ANTISEMI 的 SQL 方言是 U-SQL/Cloudera Impala。

SEMIJOIN:

Semijoins 是 U-SQL 的方式,它根据行集包含在另一个行集中的行来过滤行集。 其他 SQL 方言用 SELECT * FROM A WHERE A.key IN (SELECT B.键 FROM B) 模式。

更多信息Semi Join and Anti Join Should Have Their Own Syntax in SQL:

“半”意味着我们并没有真正加入右手边,我们只检查加入是否会为任何给定的元组产生结果。

-- IN
SELECT *
FROM Employee
WHERE DeptName IN (
  SELECT DeptName
  FROM Dept
)

-- EXISTS
SELECT *
FROM Employee
WHERE EXISTS (
  SELECT 1
  FROM Dept
  WHERE Employee.DeptName = Dept.DeptName
)

编辑:

另一种支持 SEMI/ANTISEMI join 的方言是KQL

kind=leftsemi(或 kind=rightsemi)

返回左侧与右侧匹配的所有记录。结果表仅包含左侧的列。

let t1 = datatable(key:long, value:string)  
[1, "a",  
2, "b",
3, "c"];
let t2 = datatable(key:long)
[1,3];
t1 | join kind=leftsemi (t2) on key

demo

输出:

key  value
1    a
3    c

【讨论】:

【参考方案3】:

据我了解,半连接是左连接或右连接:

What's the difference between INNER JOIN, LEFT JOIN, RIGHT JOIN and FULL JOIN?

因此,左(半)连接和“常规”连接之间的区别在于您只检索左表的数据(您的连接条件匹配)。而使用完全(外部)联接(我认为这就是您所说的传统联接的意思),您检索条件匹配的两个表的数据。

【讨论】:

左连接或右连接称为外连接semi-join 根本不是一回事:它返回一个表中的一组行,这些行受其他表中存在数据的约束,而不实际从该其他表中提取任何数据.它由EXISTS 实现,如 Iurii Ant 的回答所示。 See Relational Algebra (Semijoin) 用于理论或this excellent article 用于特定于 SQL Server 的介绍。 为什么这个错误的答案仍然被选为正确的? 几乎不正确。 Semi Join 由EXISTSWHERE IN 实现。在这两种情况下,它都充当过滤器,其中要检查的元素可以来自另一个表(或与上层选择相同的表)。

以上是关于什么是数据库中的半联接?的主要内容,如果未能解决你的问题,请参考以下文章

Spark 中的 Oracle 表之间的联接

Oracle 存储函数与查询中的联接

图文并茂~ 详解交换机中的半双工与全双工网络知识

MySQL的半一执行读

Oracle DB 使用连接显示多个表中的数据

科目三考试