CROSS JOIN
和 INNER JOIN
有什么区别?
交叉连接:
SELECT
Movies.CustomerID, Movies.Movie, Customers.Age,
Customers.Gender, Customers.[Education Level],
Customers.[Internet Connection], Customers.[Marital Status],
FROM
Customers
CROSS JOIN
Movies
内部联接:
SELECT
Movies.CustomerID, Movies.Movie, Customers.Age,
Customers.Gender, Customers.[Education Level],
Customers.[Internet Connection], Customers.[Marital Status]
FROM
Customers
INNER JOIN
Movies ON Customers.CustomerID = Movies.CustomerID
哪个更好,我为什么要使用其中一个?
CROSS JOIN
将产生所有可能的表组合。例如,100 行的 Table1 和 100 行的 Table2 将产生 10000 条记录。
x CROSS JOIN y
是 x INNER JOIN y ON 1=1
这是 Cross Join 和 Inner Join 的最佳示例。
考虑下表
表格:Teacher
x------------------------x
| TchrId | TeacherName |
x----------|-------------x
| T1 | Mary |
| T2 | Jim |
x------------------------x
表格:Student
x--------------------------------------x
| StudId | TchrId | StudentName |
x----------|-------------|-------------x
| S1 | T1 | Vineeth |
| S2 | T1 | Unni |
x--------------------------------------x
1. 内连接
内连接选择同时满足表的行。
考虑我们需要找到作为班级教师的教师及其对应的学生。在这种情况下,我们需要应用 JOIN
或 INNER JOIN
并将
https://i.stack.imgur.com/fH3fU.jpg
询问
SELECT T.TchrId,T.TeacherName,S.StudentName
FROM #Teacher T
INNER JOIN #Student S ON T.TchrId = S.TchrId
SQL 小提琴
结果
x--------------------------------------x
| TchrId | TeacherName | StudentName |
x----------|-------------|-------------x
| T1 | Mary | Vineeth |
| T1 | Mary | Unni |
x--------------------------------------x
2. 交叉连接
交叉连接选择第一个表中的所有行和第二个表中的所有行并显示为笛卡尔积,即,具有所有可能性
考虑我们需要找到所有教师学校和学生不分班主任,我们需要申请CROSS JOIN
。
https://i.stack.imgur.com/2OqzE.jpg
询问
SELECT T.TchrId,T.TeacherName,S.StudentName
FROM #Teacher T
CROSS JOIN #Student S
SQL 小提琴
结果
x--------------------------------------x
| TchrId | TeacherName | StudentName |
x----------|-------------|-------------x
| T2 | Jim | Vineeth |
| T2 | Jim | Unni |
| T1 | Mary | Vineeth |
| T1 | Mary | Unni |
x--------------------------------------x
交叉连接不合并行,如果每个表有 100 行,1 对 1 匹配,则得到 10.000 个结果,Innerjoin 在相同情况下只会返回 100 行。
这 2 个示例将返回相同的结果:
交叉连接
select * from table1 cross join table2 where table1.id = table2.fk_id
内部联接
select * from table1 join table2 on table1.id = table2.fk_id
使用最后一种方法
select * from table1 cross join table2 where table1.id = table2.fk_id
写为 select * from table1, table2 where table1.id = table2.fk_id
(将 cross join
替换为 ,
)
CROSS JOIN = (INNER) JOIN = 逗号 (",")
TL;DR SQL CROSS JOIN、(INNER) JOIN 和逗号 (",") 之间的唯一区别(除了逗号对评估顺序的优先级较低)是 (INNER) JOIN 有一个 ON 而 CROSS JOIN 和逗号没有。
再中间产品
这三个都产生了一个中间概念 SQL 风格的关系“笛卡尔”产品,也就是交叉连接,它包含每个表中一行的所有可能组合。减少行数的是 ON 和/或 WHERE。 SQL Fiddle
SQL 标准通过 product (7.5 1.b.ii) 定义
正如维基百科所说:
交叉连接 CROSS JOIN 返回连接中表行的笛卡尔积。换句话说,它将生成将第一个表中的每一行与第二个表中的每一行组合在一起的行。
内连接 [...] 连接的结果可以定义为首先取表中所有记录的笛卡尔积(或交叉连接)的结果(将表 A 中的每条记录与表 B 中的每条记录相结合)和然后返回满足连接谓词的所有记录。
“隐式连接表示法”只是在 SELECT 语句的 FROM 子句中列出要连接的表,并使用逗号分隔它们。因此它指定了一个交叉连接
重新OUTER JOIN 看我的回答What is the difference between “INNER JOIN” and “OUTER JOIN”?。
Re OUTER JOINs 并在其中使用 ON vs WHERE 请参阅我的答案 Conditions in LEFT JOIN (OUTER JOIN) vs INNER JOIN。
为什么要比较表之间的列?
当没有重复行时:
每个表都包含从某个填写 [named-]blanks 语句模板中做出真实语句的行。 (它从——满足——某个(特征)谓词提出一个真命题。)
一个基表包含从一些 DBA 给定的语句模板中做出真实语句的行: /* 客户 C.CustomerID 具有年龄 C.Age 和 ... */ FROM 客户 C 的行
联接的中间产品包含从其操作数模板的 AND 中得出真实语句的行: /* 客户 C.CustomerID 具有年龄 C.Age 和 ... AND 电影 M.Movie 由客户 M.CustomerID 租用的行和 ... */ FROM Customers C CROSS JOIN Movies M
ON & WHERE 条件被 ANDed 以提供进一步的模板。该值再次是满足该模板的行: /* 客户 C.CustomerID 具有年龄 C.Age 和 ... AND 电影 M.Movie 由客户 M.CustomerID 和 ... AND C.CustomerID = M 租用的行.CustomerID AND C.Age >= M.[Minimum Age] AND C.Age = 18 */ FROM Customers C INNER JOIN Movies M ON C.CustomerID = M.CustomerID AND C.Age >= M.[Minimum Age] WHERE C.年龄 = 18
特别是,比较表之间 (SQL) 相等的列意味着从产品中保留的来自连接表的模板部分的行对于这些列具有相同的(非 NULL)值。巧合的是,通过表之间的相等比较通常会删除很多行 - 必要且足够的是表征您想要的行。
只需为您想要的行的模板编写 SQL!
重新查询的含义(以及表与条件)请参阅:
How to get matching data from another SQL table for two different columns: Inner Join and/or Union?
Is there any rule of thumb to construct SQL query from a human-readable description?
重载“交叉连接”
不幸的是,术语“交叉连接”被用于:
中间产物。
交叉连接。
(INNER) 使用 ON 或 WHERE 连接,不会将一个表中的任何列与另一个表的任何列进行比较。 (因为这往往会返回很多中间产品行。)
这些不同的含义被混淆了。 (例如,这里的其他答案和评论。)
使用 CROSS JOIN vs (INNER) JOIN vs 逗号
常见的约定是:
当且仅当您不比较表之间的列时才使用 CROSS JOIN。那是为了表明缺乏比较是故意的。
当且仅当您比较表之间的列时,才使用 (INNER) JOIN with ON。 (加上可能的其他条件。)
不要使用逗号。
通常,不在成对表上的条件也会保留在 WHERE 中。但是可能必须将它们放入 (n INNER) JOIN ON 中,以便为 RIGHT、LEFT 或 FULL (OUTER) JOIN 的参数获取适当的行。
重新“不要使用逗号”将逗号与显式 JOIN 混合可能会产生误导,因为逗号的优先级较低。但是考虑到中间产品在 CROSS JOIN、(INNER) JOIN 和逗号的含义中的作用,上面关于根本不使用它的约定的论点是不稳定的。 CROSS JOIN 或逗号就像在 TRUE 条件下的 (INNER) JOIN。中间产品 ON 和 WHERE 都在相应的谓词中引入了 AND。然而,也可以考虑 INNER JOIN ON ——例如,仅在找到满足 ON 条件的一对输入行时才生成输出行——但它仍然返回满足条件的交叉连接行。 ON 必须在 SQL 中补充逗号的唯一原因是编写 OUTER JOIN。当然,表达式应该明确其含义;但是什么是清楚的取决于事情被认为是什么意思。
Re 维恩图 带有两个相交圆圈的维恩图可以说明相同输入的 INNER、LEFT、RIGHT 和 FULL JOIN 的输出行之间的差异。而当 ON 无条件为 TRUE 时,INNER JOIN 结果与 CROSS JOIN 相同。它还可以说明 INTERSECT、UNION 和 EXCEPT 的输入和输出行。并且当两个输入具有相同的列时,INTERSECT 结果与标准 SQL NATURAL JOIN 相同,而 EXCEPT 结果与涉及 LEFT & RIGHT JOIN 的某些习语相同。但它并没有说明 (INNER) JOIN 的一般工作原理。乍一看,这似乎是合理的。它可以为 ON、PK(主键)、FK(外键)和/或 SELECT 的特殊情况识别部分输入和/或输出。你所要做的就是确定圆圈所代表的集合的元素到底是什么。 (混乱的演示永远不会说清楚。)请记住,通常对于连接,输出行与输入行具有不同的标题。 SQL 表是袋子,而不是带有 NULL 的行集。
CROSS JOIN
。我确实想知道有多少人使用 SQL 已经熟悉笛卡尔积但无法弄清楚 CROSS JOIN
。
内部联接
仅显示两个连接表中匹配的行的连接称为内连接。这是查询和视图设计器中的默认连接。
内连接的语法
SELECT t1.column_name,t2.column_name
FROM table_name1 t1
INNER JOIN table_name2 t2
ON t1.column_name=t2.column_name
交叉连接
一种交叉连接,它产生连接中涉及的表的笛卡尔积。笛卡尔积的大小是第一个表中的行数乘以第二个表中的行数。
交叉连接的语法
SELECT * FROM table_name1
CROSS JOIN table_name2
或者我们也可以用另一种方式来写
SELECT * FROM table_name1,table_name2
现在检查下面的交叉连接查询
例子
SELECT * FROM UserDetails
CROSS JOIN OrderDetails
或者
SELECT * FROM UserDetails, OrderDetails
交叉连接
AThe CROSS JOIN 旨在生成笛卡尔积。
笛卡尔积采用两组 A 和 B,并从两组给定的数据生成对记录的所有可能排列。
例如,假设您有以下 ranks
和 suits
数据库表:
https://i.stack.imgur.com/CnotY.png
ranks
具有以下行:
| name | symbol | rank_value |
|-------|--------|------------|
| Ace | A | 14 |
| King | K | 13 |
| Queen | Q | 12 |
| Jack | J | 11 |
| Ten | 10 | 10 |
| Nine | 9 | 9 |
而 suits
表包含以下记录:
| name | symbol |
|---------|--------|
| Club | ♣ |
| Diamond | ♦ |
| Heart | ♥ |
| Spade | ♠ |
作为 CROSS JOIN 查询,如下所示:
SELECT
r.symbol AS card_rank,
s.symbol AS card_suit
FROM
ranks r
CROSS JOIN
suits s
将生成 ranks
和 suites
对的所有可能排列:
| card_rank | card_suit |
|-----------|-----------|
| A | ♣ |
| A | ♦ |
| A | ♥ |
| A | ♠ |
| K | ♣ |
| K | ♦ |
| K | ♥ |
| K | ♠ |
| Q | ♣ |
| Q | ♦ |
| Q | ♥ |
| Q | ♠ |
| J | ♣ |
| J | ♦ |
| J | ♥ |
| J | ♠ |
| 10 | ♣ |
| 10 | ♦ |
| 10 | ♥ |
| 10 | ♠ |
| 9 | ♣ |
| 9 | ♦ |
| 9 | ♥ |
| 9 | ♠ |
内部联接
另一方面,INNER JOIN 不返回两个连接数据集的笛卡尔积。
相反,INNER JOIN 从左侧表中获取所有元素,并将它们与右侧表中的记录进行匹配,以便:
如果右侧表没有匹配到记录,则从结果集中过滤掉左侧行
对于右侧表上的任何匹配记录,左侧行将重复,就好像该记录与其在右侧表上的所有关联子记录之间存在笛卡尔积一样。
例如,假设父表 post
和子表 post_comment
之间存在一对多表关系,如下所示:
https://i.stack.imgur.com/PT3ov.png
现在,如果 post
表有以下记录:
| id | title |
|----|-----------|
| 1 | Java |
| 2 | Hibernate |
| 3 | JPA |
post_comments
表有以下行:
| id | review | post_id |
|----|-----------|---------|
| 1 | Good | 1 |
| 2 | Excellent | 1 |
| 3 | Awesome | 2 |
类似于以下的 INNER JOIN 查询:
SELECT
p.id AS post_id,
p.title AS post_title,
pc.review AS review
FROM post p
INNER JOIN post_comment pc ON pc.post_id = p.id
将包括所有 post
记录及其所有关联的 post_comments
:
| post_id | post_title | review |
|---------|------------|-----------|
| 1 | Java | Good |
| 1 | Java | Excellent |
| 2 | Hibernate | Awesome |
基本上,您可以将 INNER JOIN 视为过滤后的 CROSS JOIN,其中只有匹配的记录保留在最终结果集中。
请记住,如果添加了 WHERE 子句,则交叉连接表现为内连接。例如,以下 Transact-SQL 查询产生相同的结果集。请参阅http://technet.microsoft.com/en-us/library/ms190690(v=sql.105).aspx
SQL Server 还接受以下更简单的表示法:
SELECT A.F,
B.G,
C.H
FROM TABLE_A A,
TABLE_B B,
TABLE_C C
WHERE A.X = B.X
AND B.Y = C.Y
使用这种更简单的表示法,人们不需要担心内部连接和交叉连接之间的区别。代替两个“ON”子句,有一个“WHERE”子句可以完成这项工作。如果您在确定哪些“JOIN”“ON”子句的位置有任何困难,请放弃“JOIN”符号并使用上面更简单的符号。
这不是作弊。
在使用内部连接编写查询时,如果两个表都满足条件,即两个表中的公共列完全匹配,则将从两个表中获取记录。
在使用交叉连接编写查询时,结果就像两个表中记录数的笛卡尔积。例如,如果 table1 包含 2 条记录,table2 包含 3 条记录,则查询结果为 2*3 = 6 条记录。
所以在你需要之前不要去交叉加入。
交叉连接和内连接是相同的,唯一的区别是在内连接中我们布尔过滤了笛卡尔积的一些结果
table1
x--------------------------------------x
| fieldA | fieldB | fieldC |
x----------|-------------|-------------x
| A | B | option1 |
| A | B1 | option2 |
x--------------------------------------x
table2
x--------------------------------------x
| fieldA | fieldB | fieldC |
x----------|-------------|-------------x
| A | B | optionB1 |
| A1 | B1 | optionB2 |
x--------------------------------------x
cross join
A,B,option1,A,B,optionB1
A,B,option1,A1,B1,optionB2
A,B1,option2,A,B,optionB1
A,B1,option2,A1,B1,optionB2
inner join on field1 (only with the value is the same in both tables)
A,B,option1,A,B,optionB1
A,B1,option2,A,B,optionB1
inner join on field1
A,B,option1,A,B,optionB1
在我们的数据设计中,我们决定只有一种我们用于连接的字段的情况。 Join only cross join 两个表,只获取完成特殊布尔表达式的行。
请注意,如果我们正在执行联接的字段在两个表中都为空,我们将通过过滤器。由我们或数据库制造商来添加额外的规则来避免或允许空值。坚持基本原则,它只是一个交叉连接,然后是一个过滤器。
内连接将给出两个表之间匹配记录的结果,而交叉连接则为您提供两个表之间可能的组合。
这取决于您期望的输出。
交叉连接将一个表中的所有行与另一个表中的所有行匹配。内连接匹配一个或多个字段。如果您有一个有 10 行的表和另一个有 10 行的表,那么这两个连接的行为会有所不同。
交叉连接将返回 100 行,它们不会相关,这就是所谓的笛卡尔积。内连接将记录彼此匹配。假设一个有一个主键,另一个是外键,你会得到 10 行返回。
交叉连接的通用性有限,但为了完整性而存在,并描述了在查询中未添加任何关系的连接表的结果。您可以使用交叉连接来制作单词组合或类似内容的列表。另一方面,内连接是最常见的连接。
Cross Join
,您是否认为它不会返回所有行,除非给出Where
子句?从您的评论中,初学者有更多机会感到困惑!!! @philipxy