ChatGPT解决这个技术问题 Extra ChatGPT

SQL中的CROSS JOIN与INNER JOIN

CROSS JOININNER 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 yx INNER JOIN y ON 1=1

C
Cœur

这是 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. 内连接

内连接选择同时满足表的行

考虑我们需要找到作为班级教师的教师及其对应的学生。在这种情况下,我们需要应用 JOININNER 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

图 2 的关键是复杂的:它包围了 CROSS JOIN 参数的(颜色无关)元素,一个数字(无关值)是它的一行,一行(颜色无关)是结果行。对于作为袋子的表,它不是维恩图:对于作为值的行,这是错误的;对于行作为元素,它们不能共享。对于作为集合的表,您不需要维恩图。图 1 是解释 JOIN 的常见可怕尝试。它的关键也很复杂:它只适用于作为集合的表&只有等值连接&只有一个值;它还表示与输出不同的输入。一般为 JOIN 写它。
图 1 作为相交圆维恩图的 4 种颜色中的第一种是有用且正确的:(INNER)JOIN 与 LEFT、RIGHT 和 FULL(OUTER)JOIN 但不是与 CROSS JOIN。交叉行在 JOIN 中,左/右行是 LEFT/RIGHT JOIN 中的额外(空扩展)行。它包括 CROSS JOIN 作为 (INNER) JOIN 的特例,其中非交集中没有行。
谢谢你的建议。无论如何,OP已经要求这两个连接之间的区别。我以这样一种方式回答了这个问题,任何初学者都可以很容易地理解它们之间的区别。正如你所说,我没有像在生产环境中那样给出密钥。它只是一个易于理解的示例。对于 Cross Join,您是否认为它不会返回所有行,除非给出 Where 子句?从您的评论中,初学者有更多机会感到困惑!!! @philipxy
我的评论指出,这些图表很难解释,即使人们知道他们想要表达什么并且不适合这个主题。通过“关键”(图 2 或 1)我的意思是“解释图表各部分的含义”。通过“写它”,我的意思是尝试让自己非常清楚地写出图表各部分的含义。您会发现图表很复杂,并且没有演示交叉连接与内部连接!即他们不属于你的答案。 PS 表关系键在解释 JOIN 的作用方面没有任何作用。 PPS 连接之间的唯一区别是 INNER JOIN 有一个 ON。
查看 W3Schools w3schools.com/sql/sql_join_inner.asp,他们为 INNER JOIN 提供了类似类型的图表。在发表评论之前确保你是对的@philipxy
t
t-clausen.dk

交叉连接不合并行,如果每个表有 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 替换为 ,
@Lucas 这是连接的旧语法,但它会起作用。不过,我推荐 Clausen 的版本,可读性更强。
1对1比赛是什么意思?你是什么意思“相同的情况”
@iliketocode "old syntax for joins"不清楚,你最好谈谈SQL-89和SQL-92标准
您的 INNER JOIN "100" 是一种特殊情况,您没有解释过,而您没有解释过一般情况。
p
philipxy

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) 定义 ,通过 (7.7 1.a) 定义 aka CROSS JOIN 和通过 加上 (INNER) JOIN ON 在哪里(7.7 1.b)。

正如维基百科所说:

交叉连接 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 的行集。


“中间概念 SQL 风格的笛卡尔叉积”——这是另一种说法,“它不是一组真正的有序对,但我不能避免说‘笛卡尔积’”? :) 作为一个非数学家,我遇到过“笛卡尔积”一词的唯一上下文是有人在解释 SQL 的 CROSS JOIN。我确实想知道有多少人使用 SQL 已经熟悉笛卡尔积但无法弄清楚 CROSS JOIN
@onedaywhen 运算符笛卡尔积在给定一些集合的情况下返回一组有序元组。结果是笛卡尔积。对于唤起但不是笛卡尔积的运算符,关系和 SQL 文化可悲地滥用/重载“笛卡尔积”。例如维基百科!我反对——它只会误导/混淆。然而不幸的是,在这里我只是用我自己的话模糊地描述了 SQL 交叉连接的工作原理,并遵从 Wikipedia。我将结果标记为“中间概念 SQL 风格的笛卡尔叉积”。是的,“笛卡尔”是为那些使用/期待它的人准备的。
m
modulitos

内部联接

仅显示两个连接表中匹配的行的连接称为内连接。这是查询和视图设计器中的默认连接。

内连接的语法

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

V
Vlad Mihalcea

交叉连接

AThe CROSS JOIN 旨在生成笛卡尔积。

笛卡尔积采用两组 A 和 B,并从两组给定的数据生成对记录的所有可能排列。

例如,假设您有以下 rankssuits 数据库表:

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

将生成 rankssuites 对的所有可能排列:

| 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,其中只有匹配的记录保留在最终结果集中。


当 x INNER JOIN y on 1=1 确实返回它时,“INNER JOIN 不返回两个连接数据集的笛卡尔积”有点多。当您继续尝试说的内容实际上(当然)在条件 1=1 时返回它时,“相反”也是如此。除了项目符号中的语言没有清楚地描述内部连接的结果。描述它的是它是一个不满足条件的交叉连接较少的行。同样,您使用“组合”的交叉连接语言也不清楚。
@Vlad Mihalcea inner join 确实只是一个 cross join + where 子句。您必须通过计算所有行组合来测试匹配,这意味着您只是在逐步计算笛卡尔积,同时丢弃不匹配的行对。
u
user3095896

请记住,如果添加了 WHERE 子句,则交叉连接表现为内连接。例如,以下 Transact-SQL 查询产生相同的结果集。请参阅http://technet.microsoft.com/en-us/library/ms190690(v=sql.105).aspx


d
drneel

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”符号并使用上面更简单的符号。

这不是作弊。


J
Jagadeesh G

在使用内部连接编写查询时,如果两个表都满足条件,即两个表中的公共列完全匹配,则将从两个表中获取记录。

在使用交叉连接编写查询时,结果就像两个表中记录数的笛卡尔积。例如,如果 table1 包含 2 条记录,table2 包含 3 条记录,则查询结果为 2*3 = 6 条记录。

所以在你需要之前不要去交叉加入。


仅当缺少 WHERE 子句时!
J
Javier Bañez

交叉连接和内连接是相同的,唯一的区别是在内连接中我们布尔过滤了笛卡尔积的一些结果

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 两个表,只获取完成特殊布尔表达式的行。

请注意,如果我们正在执行联接的字段在两个表中都为空,我们将通过过滤器。由我们或数据库制造商来添加额外的规则来避免或允许空值。坚持基本原则,它只是一个交叉连接,然后是一个过滤器。


s
sindhu

内连接将给出两个表之间匹配记录的结果,而交叉连接则为您提供两个表之间可能的组合。


S
Shrikant Jadhav

这取决于您期望的输出。

交叉连接将一个表中的所有行与另一个表中的所有行匹配。内连接匹配一个或多个字段。如果您有一个有 10 行的表和另一个有 10 行的表,那么这两个连接的行为会有所不同。

交叉连接将返回 100 行,它们不会相关,这就是所谓的笛卡尔积。内连接将记录彼此匹配。假设一个有一个主键,另一个是外键,你会得到 10 行返回。

交叉连接的通用性有限,但为了完整性而存在,并描述了在查询中未添加任何关系的连接表的结果。您可以使用交叉连接来制作单词组合或类似内容的列表。另一方面,内连接是最常见的连接。