182

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

哪个更好,我为什么要使用其中一个?

4

11 回答 11

203

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

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

考虑我们需要找到担任班主任的老师及其对应的学生。在这种情况下,我们需要申请JOINorINNER JOIN和 will

在此处输入图像描述

询问

SELECT T.TchrId,T.TeacherName,S.StudentName 
FROM #Teacher T
INNER JOIN #Student S ON T.TchrId = S.TchrId

结果

x--------------------------------------x
|  TchrId  | TeacherName | StudentName | 
x----------|-------------|-------------x            
|    T1    |     Mary    |    Vineeth  |
|    T1    |     Mary    |    Unni     |
x--------------------------------------x

2. 交叉连接

交叉连接选择第一个表中的所有行和第二个表中的所有行并显示为笛卡尔积,即,具有所有可能性

考虑我们需要找到学校中的所有老师和学生,而不考虑班主任,我们需要申请CROSS JOIN.

在此处输入图像描述

询问

SELECT T.TchrId,T.TeacherName,S.StudentName 
FROM #Teacher T
CROSS JOIN #Student S 

结果

x--------------------------------------x
|  TchrId  | TeacherName | StudentName | 
x----------|-------------|-------------x            
|    T2    |     Jim     |    Vineeth  |
|    T2    |     Jim     |    Unni     |
|    T1    |     Mary    |    Vineeth  |
|    T1    |     Mary    |    Unni     |
x--------------------------------------x
于 2014-02-15T06:37:42.753 回答
131

交叉连接不合并行,如果每个表中有 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

使用最后一种方法

于 2013-07-20T07:16:00.953 回答
93

CROSS JOIN = (INNER) JOIN = 逗号 (",")

TL;DR SQL CROSS JOIN、(INNER) JOIN 和逗号 (",") 之间的唯一区别(除了逗号对评估顺序的优先级较低)是 (INNER) JOIN 有一个 ON 而 CROSS JOIN 和逗号没有。


再中间产品

这三个都产生了一个中间概念 SQL 风格的关系“笛卡尔”产品,也就是交叉连接,它包含每个表中一行的所有可能组合。减少行数的是 ON 和/或 WHERE。SQL小提琴

SQL 标准通过 product (7.5 1.b.ii)定义<comma>,通过 <comma> (7.7 1.a) 定义 <cross join> aka CROSS JOIN 和通过 <comma> 加上 (INNER) JOIN ON <search condition>在哪里(7.7 1.b)。

正如维基百科所说:

交叉连接
CROSS JOIN 返回连接中表行的笛卡尔积。换句话说,它将生成将第一个表中的每一行与第二个表中的每一行组合在一起的行。

内连接
[...] 连接的结果可以定义为首先取表中所有记录的笛卡尔积(或交叉连接)的结果(将表 A 中的每条记录与表 B 中的每条记录相结合)和然后返回满足连接谓词的所有记录。

“隐式连接表示法”只是在 SELECT 语句的 FROM 子句中列出要连接的表,并使用逗号分隔它们。因此它指定了一个交叉连接

Re OUTER JOIN 看我的回答 “INNER JOIN”和“OUTER JOIN”有什么区别?.

重新 OUTER JOIN 并在其中使用 ON 与 WHERE 请参阅我 在 LEFT JOIN (OUTER JOIN) 与 INNER JOIN 中的回答条件

为什么要比较表之间的列?

当没有重复行时:

每个表都包含从某个填写 [named-]blanks 语句模板中做出真实语句的行。(它从——满足——某个(特征)谓词中提出一个真命题。)

  • 基表包含从某些 DBA 给定的语句模板中生成真实语句的行:

      /* rows where
      customer C.CustomerID has age C.Age and ...
      */
      FROM Customers C
    
  • 连接的中间产品包含从其操作数模板的 AND 中构成真正语句的行:

      /* rows where
          customer C.CustomerID has age C.Age and ...
      AND movie M.Movie is rented by customer M.CustomerID and ...
      */
      FROM Customers C CROSS JOIN Movies M
    
  • ON & WHERE 条件被 ANDed 以提供进一步的模板。该值再次是满足该模板的行:

      /* rows where
          customer C.CustomerID has age C.Age and ...
      AND movie M.Movie is rented by customer M.CustomerID and ...
      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.Age = 18
    

特别是,比较表之间 (SQL) 相等的列意味着从产品中保留的来自连接表的模板部分的行对于这些列具有相同的(非 NULL)值。巧合的是,通过表之间的相等比较通常会删除很多行——必要且足够的是描述您想要的行。

只需为您想要的行的模板编写 SQL!

重新查询(和表与条件)的含义,请参阅:
如何从另一个 SQL 表中获取两个不同列的匹配数据:内部联接和/或联合?
是否有任何经验法则可以根据人类可读的描述构造 SQL 查询?

重载“交叉连接”

不幸的是,术语“交叉连接”被用于:

  • 中间产物。
  • 交叉连接。
  • (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加入。当然,表达式应该明确其含义;但是什么是清楚的取决于事情被认为是什么意思。

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、PKs(主键)、FKs(外键)和/或 SELECT 的特殊情况。你所要做的就是确定圆圈所代表的集合的元素到底是什么。(混乱的演示永远不会说清楚。)请记住,通常对于连接,输出行与输入行具有不同的标题。SQL 表是而不是带有 NULL的行

于 2014-09-21T09:07:05.280 回答
23

内部联接

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

内连接的语法

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
于 2013-12-12T06:14:39.450 回答
15

交叉连接

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

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

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

等级和西装表

并且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,如下所示:

一对多表关系

现在,如果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 视为过滤后的 CROSS JOIN,其中只有匹配的记录保留在最终结果集中。

于 2019-12-12T08:53:32.840 回答
14

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

于 2014-03-12T13:51:01.550 回答
6

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

这不是作弊。

于 2014-08-26T16:13:15.777 回答
2

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

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

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

于 2013-07-21T04:58:48.497 回答
1

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

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

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

于 2016-02-05T11:23:26.430 回答
0

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

于 2016-02-04T16:58:35.523 回答
-1

这取决于您期望的输出。

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

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

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

于 2019-12-03T07:09:30.567 回答