此外怎么办LEFT JOIN
,RIGHT JOIN
和FULL JOIN
适合吗?
此外怎么办LEFT JOIN
,RIGHT JOIN
和FULL JOIN
适合吗?
Answers:
假设您要加入没有重复的列,这是一种很常见的情况:
A和B的内部连接给出A相交B的结果,即维恩图相交的内部。
A和B的外部连接给出A并集B的结果,即维恩图并集的外部。
例子
假设您有两个表,每个表都有一个列,数据如下:
A B
- -
1 3
2 4
3 5
4 6
请注意,(1,2)是A唯一的,(3,4)是共同的,(5,6)是B唯一的。
内部联接
使用任一等价查询的内部联接给出两个表的交集,即它们共有的两行。
select * from a INNER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b;
a | b
--+--
3 | 3
4 | 4
左外连接
左外部联接将给出A中的所有行,以及B中的所有常见行。
select * from a LEFT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b(+);
a | b
--+-----
1 | null
2 | null
3 | 3
4 | 4
右外连接
右外部联接将给出B中的所有行,以及A中的所有常见行。
select * from a RIGHT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a(+) = b.b;
a | b
-----+----
3 | 3
4 | 4
null | 5
null | 6
完全外部联接
完整的外部联接将为您提供A和B的并集,即A中的所有行和B中的所有行。如果A中的某物在B中没有对应的基准,则B部分为空,反之反之亦然。
select * from a FULL OUTER JOIN b on a.a = b.b;
a | b
-----+-----
1 | null
2 | null
3 | 3
4 | 4
null | 6
null | 5
维恩图对我来说并不是真的。
例如,它们没有显示交叉联接和内部联接之间的任何区别,或更笼统地说,它们显示了不同类型的联接谓词之间的任何区别,或者提供了推理它们如何操作的框架。
理解逻辑处理是无可替代的,无论如何,它都是相对直接的。
on
针对第1步中的所有行评估该子句,保留谓词求和的行true
(注意:实际上,查询优化器可能会找到比上面的纯粹逻辑描述更有效的查询执行方式,但最终结果必须相同)
我将从完整外部联接的动画版本开始。接下来是进一步的解释。
源表
首先从CROSS JOIN
(又称笛卡尔积)开始。它没有ON
子句,仅返回两个表中所有行的组合。
从交叉连接中选择A.颜色,B。颜色
内连接和外连接具有“ ON”子句谓词。
从A.Colour = B.Colour的内部联接B中选择A.Colour,B.Colour
上面是经典的等分连接。
内部联接条件不必一定是相等条件,也不必引用两个表(甚至其中一个表)的列。A.Colour NOT IN ('Green','Blue')
对交叉联接的每一行进行评估。
从1 = 1的内部联接B中选择A.颜色,B。颜色
对于交叉连接结果中的所有行,连接条件的评估结果均为true,因此与交叉连接相同。我将不再重复16行的图片。
外连接以同样的方式在逻辑上评价为内连接不同的是,如果左表行(左连接)不从右手表在所有它在结果中保留任何行会合NULL
的价值观右手列。
这只是将先前的结果限制为仅返回其中的行B.Colour IS NULL
。在这种特殊情况下,这些行将被保留,因为它们在右侧表中不匹配,并且查询返回表中未匹配的单个红色行B
。这称为反半联接。
为IS NULL
测试选择一列不可为空或连接条件可确保NULL
排除任何值以使此模式正常工作,并避免仅带回恰好具有该NULL
值的行,这一点很重要列以及未匹配的行。
右外部联接的行为与左外部联接类似,不同之处在于它们保留了来自右表的不匹配行,并且null扩展了左手列。
完全外部联接将左右联接的行为结合在一起,并保留左右表中不匹配的行。
交叉联接中没有行与1=0
谓词匹配。两侧的所有行均使用常规外部连接规则保留,另一侧的表的列中为NULL。
通过对前面的查询进行较小的修改,可以模拟UNION ALL
两个表中的一个。
请注意,该WHERE
子句(如果存在)在逻辑上在联接之后运行。一个常见的错误是执行左外部联接,然后在右表上包含带有条件的WHERE子句,该条件最终将排除不匹配的行。以上结束了执行外部联接...
...然后运行“ Where”子句。NULL= 'Green'
不会评估为true,因此外部联接保留的行最终会被丢弃(与蓝色联接在一起),从而有效地将联接转换回内部联接。
如果意图是仅包含B的行(其中Color为绿色)和A的所有行,而无论正确的语法是
请参阅这些示例,在SQLFiddle.com上实时运行。
联接用于合并两个表中的数据,结果是一个新的临时表。联接是基于称为谓词的事物执行的,谓词指定了执行联接所使用的条件。内部联接和外部联接之间的区别在于,内部联接将仅返回基于联接谓词实际匹配的行。例如-让我们考虑Employee和Location表:
内部联接:-内部联接通过基于联接谓词 组合两个表( Employee和 Location)的列值来创建新的结果表。该查询将 Employee的每一行与 Location的每一行进行比较,以找到满足join谓词的所有行对。当通过匹配非NULL值满足连接谓词时, Employee和 Location的每对匹配行对的列值将合并到结果行中。内部联接的SQL如下所示:
select * from employee inner join location on employee.empID = location.empID
OR
select * from employee, location where employee.empID = location.empID
现在,运行该SQL的结果如下所示:
外部联接:-外部联接 不需要两个联接表中的每个记录都具有匹配的记录。联接的表将保留每个记录,即使不存在其他匹配的记录也是如此。外连接细分为左外连接和右外连接,具体取决于保留的是表的行(左还是右)。
左外部联接:- 表 Employee和 Location的左外部联接(或简单地称为左联接)的结果始终包含“ left”表( Employee)的所有记录,即使联接条件未在其中找到任何匹配的记录“正确的”表( Location)。使用上面的表,这是用于左外部联接的SQL的样子:
select * from employee left outer join location on employee.empID = location.empID;
//Use of outer keyword is optional
现在,运行此SQL的结果如下所示:
右外部联接:-右外部联接 (或右联接)与左外部联接非常相似,除了对表的处理相反。“右”表( Location)中的每一行将至少出现在联接表中一次。如果从“左”表(不匹配的行员工)存在,NULL就会出现在列的员工对于那些在没有匹配的记录位置。这是SQL的样子:
select * from employee right outer join location on employee.empID = location.empID;
//Use of outer keyword is optional
使用上面的表,我们可以显示右外部联接的结果集是什么样的:
完全外部联接:- 完全外部联接或完全联接通过在联接结果中包括不匹配的行来保留不匹配的信息,请使用完全外部联接。它包括两个表中的所有行,而不管另一个表是否具有匹配值。
仅检索匹配的行,即A intersect B
。
SELECT *
FROM dbo.Students S
INNER JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
从第一个表中选择所有记录,并在第二个表中选择与联接的键匹配的所有记录。
SELECT *
FROM dbo.Students S
LEFT JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
从第二个表中选择所有记录,并在第一个表中选择与联接的键匹配的所有记录。
SELECT *
FROM dbo.Students S
FULL JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
简单来说:
一个内部联接仅检索匹配的行。
而外部联接从一个表中检索匹配的行,而从另一表中检索所有行..结果取决于您使用的是哪一个:
左:右表中的匹配行以及左表中的所有行
右:左表中匹配的行以及右表中的所有行或
完整:所有表中的所有行。是否有比赛无关紧要
内部联接要求联接表中存在具有相关ID的记录。
即使右侧没有任何内容,外部联接也将返回左侧的记录。
例如,您有一个Orders和一个OrderDetails表。它们通过“ OrderID”关联。
命令
订单详细信息
要求
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
INNER JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
将仅返回在OrderDetails表中也包含某些内容的订单。
如果将其更改为OUTER LEFT JOIN
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
LEFT JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
那么它将从Orders表中返回记录,即使它们没有OrderDetails记录也是如此。
通过添加where子句,您可以使用它来查找没有指示可能的孤立订单的OrderDetails的订单WHERE OrderDetails.OrderID IS NULL
。
SELECT c.id, c.status, cd.name, c.parent_id, cd.description, c.image FROM categories c, categories_description cd WHERE c.id = cd.categories_id AND c.status = 1 AND cd.language_id = 2 ORDER BY c.parent_id ASC
对SELECT c.id, c.status, cd.name, c.parent_id, cd.description, c.image FROM categories c INNER JOIN categories_description cd ON c.id = cd.categories_id WHERE c.status = 1 AND cd.language_id = 2 ORDER BY c.parent_id ASC
(MySQL)之类的请求。我不确定其他条件,它们混合得很好...
简单来说:
内部联接 ->仅从父表和子表中获取公共记录,而父表的主键与子表中的外键匹配。
左联接 ->
伪码
1.Take All records from left Table
2.for(each record in right table,) {
if(Records from left & right table matching on primary & foreign key){
use their values as it is as result of join at the right side for 2nd table.
} else {
put value NULL values in that particular record as result of join at the right side for 2nd table.
}
}
右连接:与左连接正好相反。将表名称放在LEFT JOIN右侧的Right join中,您将得到与LEFT JOIN相同的输出。
外部联接:显示两个表中的所有记录No matter what
。如果基于主键,外键,左表中的记录与右表不匹配,请使用NULL值作为连接的结果。
范例:
现在假设有2张桌子
1.employees , 2.phone_numbers_employees
employees : id , name
phone_numbers_employees : id , phone_num , emp_id
在这里,employees表是Master表,phone_numbers_employees是子表(它包含emp_id
作为连接的外键,employee.id
因此它的子表是。)
内部联接
仅当雇员表的主键(其id)与子表phone_numbers_employees(emp_id)的外键匹配时,才获取2个表的记录。
因此查询将是:
SELECT e.id , e.name , p.phone_num FROM employees AS e INNER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
如上所述,这里仅获取主键=外键上的匹配行。这里,由于连接的结果,跳过了主键=外键上的不匹配行。
左联接:
左联接保留左表的所有行,而不管右表上是否有匹配的行。
SELECT e.id , e.name , p.phone_num FROM employees AS e LEFT JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
外连接:
SELECT e.id , e.name , p.phone_num FROM employees AS e OUTER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
图表上看起来像:
答案是每个人的意思,结果也是如此。
注:
在SQLite
没有RIGHT OUTER JOIN
或FULL OUTER JOIN
。
而且也MySQL
没有FULL OUTER JOIN
。
我的答案是基于上述Note的。
当您有两个这样的表时:
--[table1] --[table2]
id | name id | name
---+------- ---+-------
1 | a1 1 | a2
2 | b1 3 | b2
CROSS JOIN / OUTER JOIN:
您可以将所有这些表数据都具有CROSS JOIN
或仅具有,
以下内容:
SELECT * FROM table1, table2
--[OR]
SELECT * FROM table1 CROSS JOIN table2
--[Results:]
id | name | id | name
---+------+----+------
1 | a1 | 1 | a2
1 | a1 | 3 | b2
2 | b1 | 1 | a2
2 | b1 | 3 | b2
INNER JOIN:
当您想基于类似的关系为上述结果添加过滤器时,table1.id = table2.id
可以使用INNER JOIN
:
SELECT * FROM table1, table2 WHERE table1.id = table2.id
--[OR]
SELECT * FROM table1 INNER JOIN table2 ON table1.id = table2.id
--[Results:]
id | name | id | name
---+------+----+------
1 | a1 | 1 | a2
LEFT [OUTER] JOIN:
当您希望以上结果中的一个表的所有行具有相同的关系时,可以使用LEFT JOIN
:(
对于RIGHT JOIN只需更改表的位置)
SELECT * FROM table1, table2 WHERE table1.id = table2.id
UNION ALL
SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
--[OR]
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
--[Results:]
id | name | id | name
---+------+------+------
1 | a1 | 1 | a2
2 | b1 | Null | Null
FULL OUTER JOIN:
如果您还希望在结果中包含其他表的所有行,则可以使用FULL OUTER JOIN
:
SELECT * FROM table1, table2 WHERE table1.id = table2.id
UNION ALL
SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
UNION ALL
SELECT Null, Null, * FROM table2 WHERE Not table2.id In (SELECT id FROM table1)
--[OR] (recommended for SQLite)
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
UNION ALL
SELECT * FROM table2 LEFT JOIN table1 ON table2.id = table1.id
WHERE table1.id IS NULL
--[OR]
SELECT * FROM table1 FULL OUTER JOIN table2 On table1.id = table2.id
--[Results:]
id | name | id | name
-----+------+------+------
1 | a1 | 1 | a2
2 | b1 | Null | Null
Null | Null | 3 | b2
好吧,根据您的需要,您可以选择满足您需求的每一个;)。
full outer join
MySQL中也没有。
INNER JOIN
两个或多个表的最典型联接。它返回表ON主键和外键关系上的数据匹配。OUTER JOIN
与相同INNER JOIN
,但也包含NULL
ResultSet上的数据。
LEFT JOIN
= INNER JOIN
+ 左表的不匹配数据与右表的Null
匹配项。RIGHT JOIN
= INNER JOIN
+ 右表的不匹配数据与Null
左表的匹配。FULL JOIN
= INNER JOIN
+ 左右表上具有Null
匹配项的不匹配数据。INNER JOIN
和OUTER JOIN
我们可以编写自我联接查询。例如:
SELECT *
FROM tablea a
INNER JOIN tableb b
ON a.primary_key = b.foreign_key
INNER JOIN tablec c
ON b.primary_key = c.foreign_key
在其他答案中,我没有看到太多有关性能和优化器的细节。
有时最好知道只有INNER JOIN
关联性,这意味着优化器具有最多的选择。它可以对连接顺序重新排序,以使其更快地保持相同的结果。优化器可以使用最多的联接模式。
通常,尝试使用INNER JOIN
而不是其他类型的联接是一个好习惯。(当然,如果可以考虑预期的结果集。)
关于这种奇怪的关联行为,这里有几个很好的例子和解释:
INNER JOIN
它比LEFT JOIN
大多数情况下都要慢,并且人们可以使用LEFT JOIN
而不是INNER JOIN
通过添加a WHERE
来删除意外的NULL
结果;)。
INNER
速度较慢?
批评了广受欢迎的红色阴影的维恩图之后,我认为发布自己的尝试是公平的。
尽管@Martin Smith的答案在很多方面都是最好的,但他只显示每个表中的键列,而我认为理想情况下还应显示非键列。
在允许的半小时内,我能做的最好,但我仍然认为这并不能充分表明空值是由于缺少键值而造成的,TableB
或者OUTER JOIN
实际上是联合而不是联接:
TableA a LEFT OUTER JOIN TableB b
TableB B RIGHT OUTER JOIN TableA a
精确的算法INNER JOIN
,LEFT/RIGHT OUTER JOIN
如下:
a
(a, b[i])
ON ...
针对每一对评估该子句:ON( a, b[i] ) = true/false?
true
,返回该组合行 (a, b[i])
。Outer Join
将返回一个(虚拟)对,Null
用于其他表的所有列:(a, Null)
用于LEFT外部联接或(Null, b)
RIGHT外部联接。这是为了确保第一个表的所有行都存在于最终结果中。注意:ON
子句中指定的条件可以是任何条件,不需要使用主键(并且您不必始终引用两个表中的列)!例如:
... ON T1.title = T2.title AND T1.version < T2.version
(=>将此示例用作示例用法:仅选择列上具有最大值的行)... ON T1.y IS NULL
... ON 1 = 0
(仅作为示例)注意:左联接=左外部联接,右联接=右外部联接。
最简单的定义
内部联接:从两个表中返回匹配的记录。
FULL OUTER JOIN:返回匹配和不匹配的记录从空从匹配的记录两个表这两个表。
左外部联接:仅从“ 左侧”表中返回匹配和不匹配的记录。
右外部联接:仅从“ 右侧”表中返回匹配和不匹配的记录。
简而言之
匹配+左不匹配+右不匹配= 完全外部联接
匹配+左不匹配= 左外连接
匹配+无匹配= 右外部连接
匹配= 内部加入
例子
假设您有两个表,每个表都有一个列,数据如下:
A B
- -
1 3
2 4
3 5
4 6
7
8
请注意,(1,2,7,8)对于A是唯一的,(3,4)是公共的,而(5,6)对于B是唯一的。
只要条件满足,INNER JOIN关键字就会从两个表中选择所有行。此关键字将通过组合两个表中满足条件的所有行来创建结果集,即,公共字段的值将相同。
select * from a INNER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b;
结果:
a | b
--+--
3 | 3
4 | 4
此联接返回联接左侧的表的所有行,以及联接右侧的表的匹配行。右侧没有匹配行的行,结果集将包含null。左联接也被称为LEFT OUTER JOIN
。
select * from a LEFT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b(+);
结果:
a | b
--+-----
1 | null
2 | null
3 | 3
4 | 4
7 | null
8 | null
select * from a RIGHT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a(+) = b.b;
结果:
a | b
-----+----
3 | 3
4 | 4
null | 5
null | 6
完全(外部)加入:
FULL JOIN通过组合LEFT JOIN和RIGHT JOIN的结果来创建结果集。结果集将包含两个表中的所有行。没有匹配的行,结果集将包含NULL值。
select * from a FULL OUTER JOIN b on a.a = b.b;
结果:
a | b
-----+-----
1 | null
2 | null
3 | 3
4 | 4
null | 6
null | 5
7 | null
8 | null
内部联接 - 使用任一等价查询的内部联接给出两个表的交集,即它们共有的两行。
左外部联接 - 左外部联接将给出A中的所有行,以及B中的所有常见行。
完全外部连接 - 完全外部连接将为您提供A和B的并集,即A中的所有行和B中的所有行。如果A中的某些内容在B中没有对应的基准,则B部分为null,反之亦然
Join is not an intersection unless the tables have the same columns
编号。您可以连接所需的任何列,如果值匹配,它们将连接在一起。
1. 内部联接:也称为联接。仅当存在match时,它才返回Left表和right表中存在的行。否则,它将返回零记录。
例:
SELECT
e1.emp_name,
e2.emp_salary
FROM emp1 e1
INNER JOIN emp2 e2
ON e1.emp_id = e2.emp_id
2. 完全外部联接:也称为完全联接。它返回在左表和右表中都存在的所有行。
例:
SELECT
e1.emp_name,
e2.emp_salary
FROM emp1 e1
FULL OUTER JOIN emp2 e2
ON e1.emp_id = e2.emp_id
3. 左外部联接:或简称为“左联接”。它返回左侧表中存在的所有行以及右侧表中的匹配行(如果有)。
4. 右外连接:也称为右连接。它从左表(如果有)返回匹配的行,并在右表中返回所有行。
加盟优势
考虑下面的两个表:
电磁脉冲
empid name dept_id salary
1 Rob 1 100
2 Mark 1 300
3 John 2 100
4 Mary 2 300
5 Bill 3 700
6 Jose 6 400
部
deptid name
1 IT
2 Accounts
3 Security
4 HR
5 R&D
在SQL查询中通常只写为JOIN。它仅返回表之间的匹配记录。
Select a.empid, a.name, b.name as dept_name
FROM emp a
JOIN department b
ON a.dept_id = b.deptid
;
empid name dept_name
1 Rob IT
2 Mark IT
3 John Accounts
4 Mary Accounts
5 Bill Security
如上所见,在输出中Jose
不会从EMP中打印出来,因为它的dept_id 6
在Department表中找不到匹配项。同样,HR
与R&D
行不从印刷系表,因为他们没有发现在EMP表的匹配。
因此,INNER JOIN或仅JOIN仅返回匹配的行。
这将返回LEFT表中的所有记录,并且仅返回RIGHT表中的匹配记录。
Select a.empid, a.name, b.name as dept_name
FROM emp a
LEFT JOIN department b
ON a.dept_id = b.deptid
;
empid name dept_name
1 Rob IT
2 Mark IT
3 John Accounts
4 Mary Accounts
5 Bill Security
6 Jose
因此,如果您观察到以上输出,则将打印LEFT表(Emp)中的所有记录,并仅打印RIGHT表中的匹配记录。
HR
并且R&D
没有从Department表中打印行,因为它们在dept_id的Emp表中找不到匹配项。
因此,LEFT JOIN返回Left表中的所有行,并且仅返回Right表中的匹配行。
也可以在此处检查DEMO 。
请参阅答案由马丁·史密斯美好illustations和解释的不同的连接,包括之间特别是不同FULL OUTER JOIN
,RIGHT OUTER JOIN
和LEFT OUTER JOIN
。
这两张表构成了JOIN
以下s 表示形式的基础:
SELECT *
FROM citizen
CROSS JOIN postalcode
结果将是所有组合的笛卡尔乘积。无需任何JOIN
条件:
INNER JOIN
与简单的相同: JOIN
SELECT *
FROM citizen c
JOIN postalcode p ON c.postal = p.postal
结果将是满足所需JOIN
条件的组合:
LEFT OUTER JOIN
是相同的 LEFT JOIN
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON c.postal = p.postal
结果将是的所有结果,citizen
即使中没有匹配项也是如此postalcode
。再次JOIN
需要一个条件:
所有示例都在Oracle 18c上运行。可以在dbfiddle.uk上获得它们,该表的截图也来自此。
CREATE TABLE citizen (id NUMBER,
name VARCHAR2(20),
postal NUMBER, -- <-- could do with a redesign to postalcode.id instead.
leader NUMBER);
CREATE TABLE postalcode (id NUMBER,
postal NUMBER,
city VARCHAR2(20),
area VARCHAR2(20));
INSERT INTO citizen (id, name, postal, leader)
SELECT 1, 'Smith', 2200, null FROM DUAL
UNION SELECT 2, 'Green', 31006, 1 FROM DUAL
UNION SELECT 3, 'Jensen', 623, 1 FROM DUAL;
INSERT INTO postalcode (id, postal, city, area)
SELECT 1, 2200, 'BigCity', 'Geancy' FROM DUAL
UNION SELECT 2, 31006, 'SmallTown', 'Snizkim' FROM DUAL
UNION SELECT 3, 31006, 'Settlement', 'Moon' FROM DUAL -- <-- Uuh-uhh.
UNION SELECT 4, 78567390, 'LookoutTowerX89', 'Space' FROM DUAL;
JOIN
和一起玩时边界模糊WHERE
CROSS JOIN
导致行显示为General Idea / INNER JOIN
:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.postal = p.postal -- < -- The WHERE condition is limiting the resulting rows
使用CROSS JOIN
获取a的结果LEFT OUTER JOIN
需要一些技巧,例如添加NULL
一行。省略了。
INNER JOIN
成为笛卡尔积。与The General Idea /相同CROSS JOIN
:
SELECT *
FROM citizen c
JOIN postalcode p ON 1 = 1 -- < -- The ON condition makes it a CROSS JOIN
在这里,内部联接实际上可以看作是交叉联接,其结果与删除的条件不匹配。此处没有任何结果行被删除。
使用INNER JOIN
获取a的结果LEFT OUTER JOIN
也需要技巧。省略了。
LEFT JOIN
结果显示为The General Idea / CROSS JOIN
:
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON 1 = 1 -- < -- The ON condition makes it a CROSS JOIN
LEFT JOIN
结果显示为The General Idea / INNER JOIN
:
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON c.postal = p.postal
WHERE p.postal IS NOT NULL -- < -- removed the row where there's no mathcing result from postalcode
在“ sql联接交叉内部外部”上的图像互联网搜索将显示大量的维恩图。我曾经在桌上放着一份印刷品。但是表示存在问题。
维恩图对于集合论非常有用,因为其中一个元素可以位于一个集合或两个集合中。但是对于数据库来说,在我看来,一个“集合”中的一个元素似乎是表中的一行,因此在其他任何表中也不存在。多个表中不存在一行。该表唯一的一行。
自连接是一个极端的情况,其中两个元素中的每个元素实际上都相同。但是它仍然不能解决以下任何问题。
在下面的讨论中,集合A
表示左边的集合(citizen
表格),而集合B
是右边的集合(postalcode
表格)。
两个集合中的每个元素都与另一个集合中的每个元素匹配,这意味着我们需要A
每个B
元素的B
数量和每个A
元素的数量才能正确表示此笛卡尔积。集合论不是针对集合中的多个相同元素建立的,因此我发现维恩图正确地表示它是不切实际/不可能的。似乎根本不合适UNION
。
这些行是不同的。的UNION
是在总7行。但是它们对于通用SQL
结果集是不兼容的。这根本不是CROSS JOIN
工作原理:
试图这样表示:
..但是现在看起来就像一个INTERSECTION
,当然不是。此外,中的元素INTERSECTION
实际上不在两个不同的集合中。但是,它看起来非常类似于以下可搜索结果:
作为参考,CROSS JOIN
可以在Tutorialgateway中看到s的一个可搜索结果。的INTERSECTION
,就像这一次,是空的。
元素的值取决于JOIN
条件。可以在每一行对该条件唯一的条件下表示这种情况。意思id=x
是只有真正的一个排。一旦在表中的一行A
(citizen
)在表中的多个行匹配B
(postalcode
下)JOIN
条件,结果有相同的问题CROSS JOIN
:该行需要被代表多次和集合论是不是真的该做。在唯一性的条件下,该图可以工作,但要记住,JOIN
条件决定了元素在图中的位置。只看JOIN
条件的值,其余部分就顺其自然:
当使用INNER JOIN
带有ON 1 = 1
使其成为的条件时,此表示形式完全瓦解CROSS JOIN
。
用自JOIN
,行是在两个表中实际上idential元素,但表示该表作为既A
与B
不是很适合。例如JOIN
,使B中的一个元素A
与另一个元素匹配的常见自我条件是ON A.parent = B.child
,使匹配从A
到B
单独的元素。从这样的例子中SQL
:
SELECT *
FROM citizen c1
JOIN citizen c2 ON c1.id = c2.leader
意思是史密斯是格林和詹森的领导者。
当一行与另一张表中的行有多个匹配项时,麻烦就再次出现。这更加复杂,因为OUTER JOIN
可以匹配空集。但是在集合论中,任何集合C
与一个空集合的并集总是正义的C
。空集不添加任何内容。表示LEFT OUTER JOIN
通常只是显示所有内容,A
以说明A
选择了in 的行,无论from中是否存在匹配项B
。然而,“匹配元件”具有与以上图示相同的问题。它们取决于条件。空集似乎已经漂移到A
:
CROSS JOIN
使用史密斯(Smith)和邮政编码在月球上查找的所有行:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
AND p.area = 'Moon';
现在,维恩图不再用于反映JOIN
。它仅用于WHERE
子句:
..那是有道理的。
如所解释的INNER JOIN
,并不是真正的INTERSECT
。但是,INTERSECT
可以将s用于单独的查询结果。这里的维恩图很有意义,因为来自单独查询的元素实际上是仅属于结果之一或两者都属于的行。显然,相交只会返回两个查询中都存在该行的结果。这SQL
将导致与上面一行相同的行WHERE
,并且维恩图也将相同:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
INTERSECT
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE p.area = 'Moon';
An OUTER JOIN
不是一个UNION
。但是,UNION
在与相同的条件下工作INTERSECT
,导致将SELECT
s 结合在一起的所有结果都返回:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
UNION
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE p.area = 'Moon';
等效于:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
OR p.area = 'Moon';
..并给出结果:
同样在这里,维恩图很有意义:
一个重要的注意事项是,只有当两个SELECT的结果的结构相同时才可以进行比较或合并,这些方法才起作用。这两个的结果将无法实现以下目的:
SELECT *
FROM citizen
WHERE name = 'Smith'
SELECT *
FROM postalcode
WHERE area = 'Moon';
..试图将结果与UNION
给出
ORA-01790: expression must have same datatype as corresponding expression
有关进一步的兴趣,请在解释JOIN和sql联接为venn图时阅读对Venn图说不。两者也都包括在内EXCEPT
。
inner join
和之间的区别outer join
如下:
Inner join
是一个基于匹配元组合并表的联接,而是outer join
一个基于匹配和不匹配元组合并表的联接。Inner join
合并两个表中的匹配行,其中省略不匹配的行,而outer join
合并两个表中的行和不匹配的行则填充空值。Inner join
就像相交运算,而outer join
像联合运算。Inner join
是两种类型,而是outer join
三种类型。outer join
比快inner join
。