Chr*_*ies 4506 sql database join inner-join outer-join
此外怎么办LEFT JOIN
,RIGHT JOIN
和FULL JOIN
适合吗?
Mar*_*son 5973
假设您正在加入没有重复的列,这是一种非常常见的情况:
A和B的内连接给出了A交叉B的结果,即维恩图交叉的内部.
A和B的外连接给出了A联合B的结果,即维恩图联合的外部部分.
例子
假设您有两个表,每个表都有一个列,数据如下:
A B
- -
1 3
2 4
3 5
4 6
Run Code Online (Sandbox Code Playgroud)
注意(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
Run Code Online (Sandbox Code Playgroud)
左外连接
左外连接将给出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
Run Code Online (Sandbox Code Playgroud)
右外连接
右外连接将给出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
Run Code Online (Sandbox Code Playgroud)
全外连接
完全外连接将为您提供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
Run Code Online (Sandbox Code Playgroud)
Mar*_*ith 680
维恩图并没有真正为我做这件事.
例如,它们没有显示交叉连接和内连接之间的任何区别,或者更一般地显示不同类型的连接谓词之间的任何区别,或者提供用于推理它们将如何操作的框架.
理解逻辑处理是无可替代的,无论如何都要相对简单.
on
根据步骤1中的所有行计算子句,并保留谓词计算结果true
(注意:在实践中,查询优化器可能会找到比上面的纯逻辑描述更有效的执行查询的方法,但最终结果必须相同)
我将从完整外连接的动画版本开始.进一步说明如下.
来源表
首先从CROSS JOIN
(AKA笛卡尔积)开始.它没有ON
子句,只返回两个表中的每个行组合.
SELECT A.Colour,B.Colour from A CROSS JOIN B
内部和外部联接具有"ON"子句谓词.
SELECT A.Colour,B.Colour from A INNER JOIN B ON A.Colour = B.Colour
以上是经典的equi join.
内连接条件不一定是相等条件,也不需要引用来自两个(或甚至任何一个)表的列.评估A.Colour NOT IN ('Green','Blue')
交叉连接的每一行返回.
选择A.Colour,B.Colour from INNER JOIN B ON 1 = 1
对于交叉连接结果中的所有行,连接条件的计算结果为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上的这些示例.
aji*_*rma 165
连接用于组合来自两个表的数据,结果是一个新的临时表.连接是基于称为谓词的东西执行的,谓词指定了用于执行连接的条件.内连接和外连接之间的区别在于内连接将仅返回基于连接谓词实际匹配的行.让我们考虑员工和位置表:
内连接: - 内连接通过基于连接谓词组合两个表( Employee和 Location)的列值来创建新的结果表.该查询将 Employee的每一行与 Location的每一行进行比较,以查找满足join-predicate的所有行对.当通过匹配非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
Run Code Online (Sandbox Code Playgroud)
外连接: - 外连接不要求两个连接表中的每个记录都有匹配的记录.即使没有其他匹配记录,联接表也会保留每条记录.外连接进一步细分为左外连接和右外连接,具体取决于保留哪个表的行(左或右).
左外连接: - 表的左外连接(或简称左连接)的结果 Employee和 Location始终包含"左"表( Employee)的所有记录,即使连接条件未找到任何匹配的记录"右"表(位置).以下是使用上表的左外连接的SQL的样子:
select * from employee left outer join location on employee.empID = location.empID;
//Use of outer keyword is optional
Run Code Online (Sandbox Code Playgroud)
右外连接: - 右外连接(或右连接)非常类似于左外连接,除非对表的处理相反."右"表(位置)中的每一行将至少出现在连接表中一次.如果从"左"表(不匹配的行员工)存在,NULL就会出现在列的员工对于那些在没有匹配的记录位置.这就是SQL的样子:
select * from employee right outer join location on employee.empID = location.empID;
//Use of outer keyword is optional
Run Code Online (Sandbox Code Playgroud)
使用上面的表格,我们可以显示右外连接的结果集是什么样的:
完全外部联接: -
完全外部联接或完全联接是通过在联接的结果中包含不匹配的行来保留不匹配的信息,使用完整的外部联接.它包括来自两个表的所有行,无论另一个表是否具有匹配值.
Tus*_*har 128
仅检索匹配的行,即A intersect B
.
SELECT *
FROM dbo.Students S
INNER JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
Run Code Online (Sandbox Code Playgroud)
选择第一个表中的所有记录,以及第二个表中与连接键匹配的所有记录.
SELECT *
FROM dbo.Students S
LEFT JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
Run Code Online (Sandbox Code Playgroud)
选择第二个表中的所有记录,以及第一个表中与连接键匹配的所有记录.
SELECT *
FROM dbo.Students S
FULL JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
Run Code Online (Sandbox Code Playgroud)
vid*_*har 108
简单来说:
一个内部联接仅检索匹配的行.
而一个外连接检索一个表匹配的行和其他表中的所有行....结果取决于你使用哪一种:
左:右表中匹配的行和左表中的所有行
右:左表中匹配的行和右表中的所有行或
完整:所有表中的所有行.是否有匹配并不重要
180*_*ION 101
如果在连接的另一侧(右侧)存在匹配记录,则内部联接仅显示行.
(左)外连接显示左侧每条记录的行,即使连接的另一侧(右侧)没有匹配的行.如果没有匹配的行,则另一侧(右侧)的列将显示NULL.
Bri*_*ght 76
内部联接要求联接表中存在具有相关ID的记录.
即使右侧没有任何内容,外部联接也将返回左侧的记录.
例如,您有一个Orders和一个OrderDetails表.它们与"OrderID"相关联.
命令
订单详细信息
请求
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
INNER JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
Run Code Online (Sandbox Code Playgroud)
只会返回OrderDetails表中也有内容的订单.
如果您将其更改为OUTER LEFT JOIN
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
LEFT JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
Run Code Online (Sandbox Code Playgroud)
然后它将从Orders表返回记录,即使它们没有OrderDetails记录.
您可以使用此命令通过添加where子句来查找没有任何指示可能的孤立订单的OrderDetails的订单WHERE OrderDetails.OrderID IS NULL
.
Pra*_*tik 65
简单来说:
内部联接 - >从父表和子表中获取常用记录WHERE主表的主键与子表中的外键匹配.
左连接 - >
伪代码
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.
}
}
Run Code Online (Sandbox Code Playgroud)
右连接:与左连接完全相反.将表的名称放在右连接中右侧的LEFT JOIN中,得到与LEFT JOIN相同的输出.
外连接:显示两个表中的所有记录No matter what
.如果Left表中的记录与Primary,Forieign键的右表不匹配,则使用NULL值作为join的结果.
示例:
让我们假设现在有2个表
1.employees , 2.phone_numbers_employees
employees : id , name
phone_numbers_employees : id , phone_num , emp_id
Run Code Online (Sandbox Code Playgroud)
这里,employees表是Master表,phone_numbers_employees是子表(它包含emp_id
连接employee.id
所以其子表的外键.)
内联合
仅记入2个表的记录如果employees表的主键(其id)与Child表phone_numbers_employees(emp_id)的外键匹配.
所以查询将是:
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;
Run Code Online (Sandbox Code Playgroud)
这里只取主键=外键上的匹配行,如上所述.作为连接结果,主键=外键上的非匹配行被跳过.
左连接:
左连接保留左表的所有行,无论是否在右表上都有匹配的行.
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;
Run Code Online (Sandbox Code Playgroud)
外连接:
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;
Run Code Online (Sandbox Code Playgroud)
从图形上看,它看起来像:
vij*_*mar 55
您可以使用INNER JOIN
从两个匹配的表中返回所有行.即在结果表中,所有行和列都将具有值.
在OUTER JOIN
结果表中可能有空列.外连接可以是LEFT
或RIGHT
.
LEFT OUTER JOIN
返回第一个表中的所有行,即使第二个表中没有匹配项也是如此.
RIGHT OUTER JOIN
返回第二个表中的所有行,即使第一个表中没有匹配项也是如此.
小智 52
INNER JOIN
要求在比较两个表时至少存在匹配.例如,表A和表B表示A 8 B(A交点B).
LEFT OUTER JOIN
并且LEFT JOIN
是一样的.它给出了两个表中匹配的所有记录以及左表的所有可能性.
同样,RIGHT OUTER JOIN
和RIGHT JOIN
是相同的.它给出了两个表中匹配的所有记录以及右表的所有可能性.
FULL JOIN
是复制LEFT OUTER JOIN
和RIGHT OUTER JOIN
不复制的组合.
shA*_*A.t 41
答案是每个人的意思,所以在结果中.
注:
在SQLite
没有RIGHT OUTER JOIN
或FULL OUTER JOIN
.
而且也MySQL
没有FULL OUTER JOIN
.
我的回答是基于上面的注释.
如果有两个这样的表:
--[table1] --[table2]
id | name id | name
---+------- ---+-------
1 | a1 1 | a2
2 | b1 3 | b2
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
那么,根据您的需要,您可以选择满足您需求的每一个;).
Kan*_*gh 33
内部联接.
连接是组合两个表中的行.一个内连接尝试根据您在查询中指定的标准,这两个表匹配,并且只返回匹配的行.如果连接中第一个表中的一行与第二个表中的两个行匹配,则结果中将返回两行.如果第一个表中的某行与第二个表中的行不匹配,则不会返回该行; 同样,如果第二个表中的某行与第一个表中的行不匹配,则不会返回该行.
外加入.
一个左连接试图找到第二个表匹配第一个表中的行的行.如果找不到匹配项,它将返回第一个表中的列,并将第二个表中的列留空(null).
Laj*_*res 25
在其他答案中,我没有看到关于性能和优化器的更多细节.
有时候很高兴知道只有INNER JOIN
关联才意味着优化器有最多的选择.它可以重新排序连接顺序,以便更快地保持相同的结果.优化器可以使用最多的连接模式.
通常,尝试使用INNER JOIN
而不是使用不同类型的连接是一种好习惯.(当然,如果可以考虑预期的结果集.)
关于这种奇怪的联想行为,这里有几个很好的例子和解释:
Pre*_*raj 25
INNER JOIN
两个或多个表的最典型连接.它返回表ON主键和forignkey关系的数据匹配.OUTER JOIN
INNER JOIN
与之相同,但它也包含NULL
ResultSet上的数据.
LEFT JOIN
= INNER JOIN
+左表的不匹配数据,右表上有Null匹配.Null
= RIGHT JOIN
+右表的不匹配数据,左表上有Null匹配.INNER JOIN
= Null
+左表和左表上的匹配数据不匹配.FULL JOIN
和INNER 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
Run Code Online (Sandbox Code Playgroud)
S.S*_*han 23
精确的算法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
(就像样品一样)注意:左连接=左外连接,右连接=右外连接.
one*_*hen 22
在批评了备受喜爱的红色阴影维恩图之后,我认为发布自己的尝试是公平的.
虽然@Martin Smith的答案在很长一段时间内是最好的,但他只显示了每个表中的键列,而我认为理想情况下也应该显示非键列.
在允许的半小时内我能做的最好的事情,我仍然认为它没有充分显示由于缺少键值TableB
或者OUTER JOIN
实际上是联合而不是连接而存在空值:
Aks*_*ale 18
最简单的定义
内部联接:返回两个表中的匹配记录.
完全外部联接:从两个表中返回匹配和不匹配的记录,其中包含来自两个表的不匹配记录的空值.
左外连接:仅从左侧的表中返回匹配和不匹配的记录.
右外连接:仅从右侧的表中返回匹配和不匹配的记录.
简而言之
匹配+左无匹配+右无匹配= 完全外连接
匹配+左无匹配= 左外连接
匹配+右无匹配= 右外连接
匹配= 内部加入
Scr*_*tte 12
请参阅Martin Smith的回答,以获得对不同连接的更好说明和解释,包括特别是,和之间的差异。FULL OUTER JOIN
RIGHT OUTER JOIN
LEFT OUTER JOIN
这两个表构成了JOIN
以下 s表示的基础:
SELECT *
FROM citizen
CROSS JOIN postalcode
Run Code Online (Sandbox Code Playgroud)
结果将是所有组合的笛卡尔积。无需JOIN
条件:
INNER JOIN
与简单的相同: JOIN
SELECT *
FROM citizen c
JOIN postalcode p ON c.postal = p.postal
Run Code Online (Sandbox Code Playgroud)
结果将是满足所需JOIN
条件的组合:
LEFT OUTER JOIN
是相同的 LEFT JOIN
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON c.postal = p.postal
Run Code Online (Sandbox Code Playgroud)
其结果将是一切从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;
Run Code Online (Sandbox Code Playgroud)
JOIN
和玩时边界模糊WHERE
CROSS JOIN
导致行为 The 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
Run Code Online (Sandbox Code Playgroud)
使用CROSS JOIN
得到的结果的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
Run Code Online (Sandbox Code Playgroud)
这就是内连接可以真正被视为交叉连接的地方,结果与删除的条件不匹配。这里没有删除任何结果行。
使用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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
在互联网上搜索“sql join cross inner external”将显示大量维恩图。我曾经在我的桌子上有一份印刷版。但是在表示上存在问题。
维恩图非常适合集合论,其中一个元素可以在一个或两个集合中。但是对于数据库,一个“集合”中的元素对我来说似乎是表中的一行,因此也不存在于任何其他表中。多个表中不存在一行。一行对于表来说是唯一的。
自连接是一种极端情况,其中每个元素实际上在两个集合中都是相同的。但它仍然不存在以下任何问题。
在下面的讨论中,集合A
代表左边的集合(citizen
表),集合B
是右边的集合(postalcode
表)。
两个集合中的每个元素都与另一个集合中的每个元素匹配,这意味着我们需要A
每个B
元素的B
数量和每个A
元素的数量来正确表示这个笛卡尔积。集合论不是为集合中的多个相同元素制定的,所以我发现维恩图正确地表示它不切实际/不可能。好像一点都UNION
不合适。
行是不同的。的UNION
是在总7行。但是它们对于一个共同的SQL
结果集是不兼容的。这根本不是 a 的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
条件的a时,这种表示完全崩溃CROSS JOIN
。
用自JOIN
,行是在两个表中实际上idential元素,但表示该表作为既A
与B
不是很适合。例如JOIN
,使元素 inA
与B 中的不同元素匹配的常见自条件是ON A.parent = B.child
,使匹配从A
到B
单独的元素。从SQL
像这样的例子来看:
SELECT *
FROM citizen c1
JOIN citizen c2 ON c1.id = c2.leader
Run Code Online (Sandbox Code Playgroud)
意思是史密斯是格林和詹森的领袖。
当一行与另一个表中的行有多个匹配时,麻烦又开始了。这更加复杂,因为OUTER JOIN
可以认为匹配空集。但是在集合论中,任何集合C
和空集合的并集总是公正的C
。空集不添加任何内容。这的表示LEFT OUTER JOIN
通常只是显示所有的,A
以说明A
无论是否存在匹配,都会选择in的行B
。然而,“匹配元素”具有与上图相同的问题。它们取决于条件。空集似乎已经徘徊到A
:
CROSS JOIN
在月球上用史密斯和邮政编码查找 a 中的所有行:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
AND p.area = 'Moon';
Run Code Online (Sandbox Code Playgroud)
现在维恩图不用于反映JOIN
. 它仅用于WHERE
子句:
..这是有道理的。
正如所解释的, anINNER JOIN
并不是真正的INTERSECT
. 但是INTERSECT
s 可用于单独查询的结果。这里维恩图是有道理的,因为来自单独查询的元素实际上是仅属于一个结果或两者的行。Intersect 显然只会返回两个查询中都存在该行的结果。这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';
Run Code Online (Sandbox Code Playgroud)
AnOUTER 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';
Run Code Online (Sandbox Code Playgroud)
这相当于:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
OR p.area = 'Moon';
Run Code Online (Sandbox Code Playgroud)
..并给出结果:
这里还有一个维恩图是有道理的:
一个重要的注意事项是,这些仅在两个 SELECT 的结果结构相同时才起作用,从而可以进行比较或联合。这两个的结果将无法实现:
SELECT *
FROM citizen
WHERE name = 'Smith'
Run Code Online (Sandbox Code Playgroud)
SELECT *
FROM postalcode
WHERE area = 'Moon';
Run Code Online (Sandbox Code Playgroud)
..试图将结果与UNION
给出一个
ORA-01790: expression must have same datatype as corresponding expression
Run Code Online (Sandbox Code Playgroud)
如需进一步的兴趣,请阅读在将 JOIN和sql 连接解释为维恩图时对维恩图说不。两者也涵盖EXCEPT
。
关于这个主题有很多错误信息,包括 Stack Overflow 上的这里。
left join on
(又名left outer join on
)返回inner join on
行union all
通过扩展无与伦比的左表列null
秒。
right join (on
又名 right outer join on
)返回inner join on
行union all
无法比拟的右表行延长了null
秒。
full join on
(又名full outer join on
)返回inner join on
行union all
通过扩展无与伦比的左表中的行null
小号union all
无与伦比的右表中的行通过延长null
秒。
(SQL Standard 2006 SQL/Foundation 7.7 Syntax Rules 1, General Rules 1 b, 3 c & d, 5 b.)
因此,outer join
在您知道所inner join
涉及的基础知识之前,请不要这样做。
找出哪些行inner join on
返回:
SQL 中的 CROSS JOIN 与 INNER JOIN
这也解释了为什么维恩(类)图对内连接和外连接没有帮助。
有关为什么维恩(类似)图对连接没有帮助的更多信息:自然连接的
维恩图
简单来说,
1. INNER JOIN或EQUI JOIN:返回仅匹配两个表中的条件的结果集.
2. OUTER JOIN:即使条件匹配与否,也返回两个表中所有值的结果集.
3. LEFT JOIN:返回左表中所有值的结果集,只返回与右表中的条件匹配的行.
4. RIGHT JOIN:返回右表中所有值的结果集,只返回与左表中的条件匹配的行.
5. 完全加入:完全加入和全外加入是相同的.
内连接-使用任一等效查询的内连接给出两个表的交集,即它们共有的两行。
左外连接-左外连接将给出 A 中的所有行,以及 B 中的所有公共行。
全外连接-全外连接会给你 A 和 B 的并集,即 A 中的所有行和 B 中的所有行。如果 A 中的某些内容在 B 中没有相应的数据,则 B 部分是null,反之亦然
1.内连接:也称为连接。它仅在存在 match 时返回 Left table 和 right table 中存在的行。否则,它返回零记录。
例子:
SELECT
e1.emp_name,
e2.emp_salary
FROM emp1 e1
INNER JOIN emp2 e2
ON e1.emp_id = e2.emp_id
Run Code Online (Sandbox Code Playgroud)
2.全外联接:也称为全联接。它返回存在于左表和右表中的所有行。
例子:
SELECT
e1.emp_name,
e2.emp_salary
FROM emp1 e1
FULL OUTER JOIN emp2 e2
ON e1.emp_id = e2.emp_id
Run Code Online (Sandbox Code Playgroud)
3.左外连接:或简称为左连接。它返回左表中存在的所有行以及右表中的匹配行(如果有)。
4.右外连接:也称为右连接。它从左表(如果有)返回匹配的行,以及右表中存在的所有行。
联接的优势
通过一个例子可以更容易地解释连接:
要模拟存储在单独表中的人员和电子邮件,
表 A 和表 B 由 Table_A 连接。id = 表_B。名称_id
内部联接
仅显示匹配的 id 行。
外连接
显示表 A的匹配 ID 和不匹配行。
显示表 B的匹配 ID 和不匹配行。
注意:MySQL 上不支持完全外连接
归档时间: |
|
查看次数: |
2278242 次 |
最近记录: |